The online racing simulator
StreamReader And String Cutting
(17 posts, started )
StreamReader And String Cutting
I'm trying to extract a string from log.txt with StreamReader but the problem is that I need it to read from last line to first.

Also I don't know how to cut from that string specific text between ": " and " (" like the Ip

Sep 29 20:04:40 Authorised : 127.0.0.1 (username)

I will probably find out how to take the ip from the string but I need some directions with the StreamReader...

Thanks!
It's generally not possible to read a file stream backwards, you can however store the results in a list and traverse through the list from last element to first. (It also might be a good idea to save the absolute position of the EOF and start reading from that position when you read the log file again to check if it changes. I'd have to look up how is this done in C#).

String class in C# provides a Split() method which splits a string into multiple strings separated by a given delimiter. For instance, calling Split("_") on string "Hello,_World!" will return strings "Hello," and "World!". There is also an IndexOf() method which returns the index of a given substring in a string. Calling IndexOf(",_") on the previous string will return 5.

EDIT: It is perfectly possible to read a file backwards because file is nothing but an array of bytes. Reading streams backwards is what cannot be done, because while you're reading the beginning of the stream, the end of it might not yet be available (think Youtube videos). With that in mind you could probably access the log file in a binary mode, look for EOLs and create strings from segments between two EOLs.
Thanks for your answer

EDIT:

Oct 04 Authorised : ip (name)
Oct 06 Authorised : ip (name)

The problem was that it was reading always the first line which could've been outdated , But you gave me an idea.
I stored the first line in a string (ex: Pinfo) , and then used statement
If (read line != Pinfo) // != means the opposite of == , which can also be as (read line == Pinfo == false)
{
read the line
}

So now its always reading the last available line



Oh and about the extracting text

the line : Oct 03 13:03:02 Authorised : 99.99.99.99 (username)

int pFrom = info.IndexOf(": ") + ": ".Length;
int pTo = info.LastIndexOf(" (");

string result = info.Substring(pFrom, pTo - pFrom);


result being the ip
Hello,
Thanks alot for the nice commands above, that was very helpful.

But i have met a problem that i couldn't fix, and i have read what wrote above 2-3 times but couldn't understand what to do.

My problem is InSim always gets the IP from the first line, please explain more to do it right?

Thanks alot!
Hello,
I have met another problem,

I have added those codes to my FileInfo.cs Folder.

static public string GetUserIPAddress(string Username)
{
StreamReader Sr = new StreamReader(UserInfo + "\\IP.txt");
string line = null;

int pFromUsername = line.IndexOf(" (") + " (".Length;
int pToUsername = line.LastIndexOf(")");
string UsernameResult = line.Substring(pFromUsername, pToUsername - pFromUsername);

while ((line = Sr.ReadLine()) != null)
{
if (UsernameResult == Username)
{
int pFrom = line.IndexOf(": ") + ": ".Length;
int pTo = line.LastIndexOf(" (");

string IP = line.Substring(pFrom, pTo - pFrom);
return IP + " " + UsernameResult;
}
}
Sr.Close();
return "";
}

and i have added this code to Form1.cs Folder inside IS_NCN Packet.

var Conn = Connections[GetConnIdx(NCN.UCID)];
Conn.IPAddress = FileInfo.GetUserIPAddress(Conn.Username);
MsgAll("^1" + Conn.IPAddress);

When i added that code to NCN Packet, it bugs the whole Packet, it doesnt send Welcome messages and everything inside that packet.

I tried to replace that code to another Packet, it also bugged it, and NCN worked perfectly when i removed that code from it, any idea please?

I'm currently using my editted 1.1.1.7 lfs external library, but i tried the original one, happened same :/
Quote from HonzaQ4 :Hello,
I have met another problem,

I have added those codes to my FileInfo.cs Folder.

static public string GetUserIPAddress(string Username)
{
StreamReader Sr = new StreamReader(UserInfo + "\\IP.txt");
string line = null;

int pFromUsername = line.IndexOf(" (") + " (".Length;
int pToUsername = line.LastIndexOf(")");
string UsernameResult = line.Substring(pFromUsername, pToUsername - pFromUsername);

while ((line = Sr.ReadLine()) != null)
{
if (UsernameResult == Username)
{
int pFrom = line.IndexOf(": ") + ": ".Length;
int pTo = line.LastIndexOf(" (");

string IP = line.Substring(pFrom, pTo - pFrom);
return IP + " " + UsernameResult;
}
}
Sr.Close();
return "";
}

and i have added this code to Form1.cs Folder inside IS_NCN Packet.

var Conn = Connections[GetConnIdx(NCN.UCID)];
Conn.IPAddress = FileInfo.GetUserIPAddress(Conn.Username);
MsgAll("^1" + Conn.IPAddress);

When i added that code to NCN Packet, it bugs the whole Packet, it doesnt send Welcome messages and everything inside that packet.

I tried to replace that code to another Packet, it also bugged it, and NCN worked perfectly when i removed that code from it, any idea please?

I'm currently using my editted 1.1.1.7 lfs external library, but i tried the original one, happened same :/

Aren't the lines 3 - 5 supposed to go inside the while loop?
Sorry for the late answer,
But i have added the last 3 lines under "while" and met the same BUG, about the first 2 lines, im sure theirs place is right, and got that working on other stats.

Any other ideas?
Your code doesn't do a lot of things it should. It doesn't check if the file you're trying to open exists and that it's readable. It assumes that the characters you're searching for are always there. It also uses something called "UserInfo" which seems to be a global variable - that's usually a bad practice. There are many reasons why a code like this would break. Also, comparing string contents with "==" operator doesn't do what you want in C#. Use String.Equals() instead.
Dude, I used the exact code but without Username check, and it worked and gave me the IP, if you read my post above, i asked why it keeps reading the first line, because i figured out how to get the IP, but didn't know why it keeps reading the first line, so when i was waiting an answer, i added that new code to check the username before getting the IP, and it BUGGED the whole packet, and i came here with another error.

About UserInfo, it's a file where i have player's stats, and inside that folder i created IP.txt, and wrote there some lines, here are they:
LOL
Oct 03 13:03:02 Authorised : 99.99.99.99 (blabla)
Oct 04 14:04:03 Authorised : 99.99.99.90 (ablabl)
Oct 05 15:05:04 Authorised : 99.99.90.99 (glagla)

that's it.

I hope you understand what i meant.
Thanks a lot for your time.
To be honest I'm not really clear about what you mean, but in any case, your code should probably look more like this.


static public bool GetUserIPAddress(string Username, out string OutputString) {
const string Path = UserInfo + "\\IP.txt";
StreamReader Sr;
string Line;

if (!File.Exists(Path)) {
return false;
}

try {
Sr = new StreamReader(Path);
} catch (Exception Ex) {
Console.WriteLine("Unable to open IP.txt for reading: " + Ex.ToString());
return false;
}

try {
while ((Line = Sr.ReadLine()) != null) {
int FromIdx, ToIdx;
string UsernameRead;

FromIdx = Line.IndexOf(" (") + " (".Length;
if (FromIdx < 0) {
return false;
}
ToIdx = Line.LastIndexOf(")");
if (ToIdx < 0) {
return false;
}
if (ToIdx < FromIdx) {
return false;
}
UsernameRead = Line.Substring(FromIdx, ToIdx - FromIdx);

if (UsernameRead.Equals(Username)) {
string IPStr;

FromIdx = Line.IndexOf(": ") + ": ".Length;
if (FromIdx < 0) {
return false;
}
ToIdx = Line.IndexOf(" (");
if (ToIdx < 0) {
return false;
}
if (ToIdx < FromIdx) {
return false;
}
IPStr = Line.Substring(FromIdx, ToIdx - FromIdx);
OutputString = IPStr + " " + Username;
return true;
}
}
} catch (OutOfMemoryException Ex) {
Console.WriteLine("Not enough memory to allocate input buffer.");
return false;
} catch (IOException Ex) {
Console.WriteLine("I/O error while reading IP.txt");
return false;
}

return false;
}

This is definitely not the best solution to this problem but at least it shouldn't explode when it tries to read a malformed line in that file.
It give me red lines if i have this line like this:

static public bool GetUserIPAddress(const string Username, out string OutputString)

MVS Removes the red lines when i have it like this:

static public bool GetUserIPAddress(string Username, string OutputString)

Any idea?
Thanks alot!
There is no "const" qualifier for function parameters in C#, "out" qualifier is needed in this case.
I'm pretty sure know that "out" is needed here, but i can't use it, it gives me red lines.

I will think little and come back with an answer.
After million of trys, didn't work.

here what i coded.

static public string GetUserFuckingIP(string Username)
{
const string Path = UserInfo + "\\IP.txt";
StreamReader Sr;
string Line;

if (!File.Exists(Path))
{
return "";
}

try
{
Sr = new StreamReader(Path);
}
catch (Exception Ex)
{
Console.WriteLine("Unable to open IP.txt for reading: " + Ex.ToString());
return "";
}
try
{
while ((Line = Sr.ReadLine()) != null)
{
int FromIdx, ToIdx;
string UsernameRead;

FromIdx = Line.IndexOf(" (") + " (".Length;
if (FromIdx < 0)
{
return "";
}
ToIdx = Line.LastIndexOf(")");
if (ToIdx < 0)
{
return "";
}
if (ToIdx < FromIdx)
{
return "";
}
UsernameRead = Line.Substring(FromIdx, ToIdx - FromIdx);

if (UsernameRead.Equals(Username))
{
string IPStr;

FromIdx = Line.IndexOf(": ") + ": ".Length;
if (FromIdx < 0)
{
return "";
}
ToIdx = Line.IndexOf(" (");
if (ToIdx < 0)
{
return "";
}
if (ToIdx < FromIdx)
{
return "";
}
IPStr = Line.Substring(FromIdx, ToIdx - FromIdx);
//OutputString = IPStr + " " + Username;
return IPStr + " " + Username;
}
}
return "";
}
catch (IOException)
{
Console.WriteLine("I/O error while reading IP.txt");
return "";
}
}

This works for me. Apparently the "out" qualified variables must be assigned to in the function no matter what.


public static void Main (string[] args)
{
string to_print;
if (!MakeSomeString("radicality", out to_print))
return;

Console.WriteLine(to_print);
Console.ReadKey(false);
}

private static bool MakeSomeString(string source, out string result)
{
result = "";

if (source.Length == 0)
return false;


result = source + " mangled";
return true;
}

Quote from MadCatX :Also, comparing string contents with "==" operator doesn't do what you want in C#.

Yes it does. String is a special case where == is overloaded to compare value instead of reference. (MSDN)


A couple of issues with the code:


1.
All cases of
return "";

within the while loop should be
continue;

If you use
return "";

it will exit the function at the first sniff of a line that doesn't contain an IP - if you're scanning a log file, that means it'll quit on line 1. Continue will instead move on to the next line, which is probably what you want.



2.
FromIdx = Line.IndexOf(" (") + " (".Length;

and
FromIdx = Line.IndexOf(": ") + ": ".Length;

will return 1 instead of the expected -1 if the string is not found. You need to check the result of .IndexOf() before adding anything to FromIdx:
FromIdx = Line.IndexOf(" (");
if (FromIdx < 0)
{
continue;
}
FromIdx += " (".Length;

3.
If anyone types ": blub (Somebody'sUsername)" into chat, it won't return what you're looking for.



P.S.
You're probably better off doing this kind of thing using Regex. It'll be more reliable, probably faster and can be done in something like 10 or so lines of code.

P.P.S
Also, I just realised that code will still only find the first IP for that user, not the latest.
You'll need to define IPStr at the start of the function, keep running the while loop until you hit EOF, then return the latest version of IPStr.
Quote from Degats :
Quote from MadCatX :Also, comparing string contents with "==" operator doesn't do what you want in C#.

Yes it does. String is a special case where == is overloaded to compare value instead of reference. (MSDN)


A couple of issues with the code:


1.
All cases of
return "";

within the while loop should be
continue;

If you use
return "";

it will exit the function at the first sniff of a line that doesn't contain an IP - if you're scanning a log file, that means it'll quit on line 1. Continue will instead move on to the next line, which is probably what you want.



2.
FromIdx = Line.IndexOf(" (") + " (".Length;

and
FromIdx = Line.IndexOf(": ") + ": ".Length;

will return 1 instead of the expected -1 if the string is not found. You need to check the result of .IndexOf() before adding anything to FromIdx:
FromIdx = Line.IndexOf(" (");
if (FromIdx < 0)
{
return "";
}
FromIdx += " (".Length;

3.
If anyone types ": blub (Somebody'sUsername)" into chat, it won't return what you're looking for.



P.S.
You're probably better off doing this kind of thing using Regex. It'll be more reliable, probably faster and can be done in something like 10 or so lines of code.

P.P.S
Also, I just realised that code will still only find the first IP for that user, not the latest.
You'll need to define IPStr at the start of the function, keep running the while loop until you hit EOF, then return the latest version of IPStr.

These pieces of information above was hell great! Best of love to you all! Thanks alot!!

StreamReader And String Cutting
(17 posts, started )
FGED GREDG RDFGDR GSFDG