What is the proper way to make a queue inside a class? - c#

I'm trying to make a queue of orders for my clients.
But the last added value replace all the values ​​in the queue.
Debbuging the code i've see that when a value is enqueued it overrides all the other values in the queue.
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Starting...");
byte[] dataInit = new byte[] { 0x00 };
Client clientTest = new Client();
for (int i = 0; i <= 5; i++)
{
dataInit[0]++;
Console.WriteLine("Adding Order - i = {0}; Order: {1}.", i, BitConverter.ToString(dataInit));
clientTest.AddOrder(dataInit);
Console.WriteLine("Peeking Order - i = {0}; Order: {1}", i, BitConverter.ToString(clientTest.PeekOrder()));
}
for (int i = 0; i <= 5; i++)
{
Console.WriteLine("Removing order - i = {0}; Order: {1}.", i, BitConverter.ToString(clientTest.RemoveOrder()));
}
Console.WriteLine("Press Any Key...");
Console.Read();
}
class ClientOrder
{
public byte[] Order;
public ClientOrder(byte[] data)
{
Order = data;
}
}
class Client
{
public Queue<ClientOrder> ClientOrders = new Queue<ClientOrder>();
public void AddOrder(byte[] orderToAdd)
{
ClientOrders.Enqueue(new ClientOrder(orderToAdd));
}
public byte[] RemoveOrder()
{
ClientOrder toReturn = ClientOrders.Dequeue();
return toReturn.Order;
}
public byte[] PeekOrder()
{
ClientOrder toReturn = ClientOrders.Peek();
return toReturn.Order;
}
}
}
i've expected that the queue was in order [0-6]. but the actual output is {06,06,06,06,06,06} (The last value added).

You are actually sharing the same reference to byte[] and then with every Enqueue you actually replace all the elements in the queue as they all reference the same array. You should make a copy when creating ClientOrder. The easy way is using Linq, but there are also other possibilities.
public ClientOrder(byte[] data)
{
Order = data.ToArray();
}
or other way around as Jeff said

Related

No errors in Visual Studio, Code Executes but something not right C# (updated! problem in String.Insert)

I'm writing a program for schoolwork, that's supposed to generate a 10 000 "movie" list. A single "movie" consist of a string in a form "moviename year director". I say "movie" because movie name and director are supposed to be randomly generated with letters from a-z.
I wrote the following logic to generate one such "movie". Movie name and director are random letter combination in length between 4-10 charachters. Code gives no errors in visual studio, executes, but shows blank. If I wrote correctly, then this code should generate one such string and print it, yet console is blank.
Do while loop is there to check if, however unlikely, there is a double item in the List (this is for when I do the 10 000 version).
In short, I dont understand what am I doing wrong?
using System;
using System.Collections.Generic;
using System.Linq;
namespace Experiment
{
class Program
{
static void Main(string[] args)
{
Movies();
Console.ReadKey();
}
public static void Movies()
{
List<string> movieList = new List<string>();
bool check = false;
do
{
string movie = "";
for (int i = 0; i < GetNum(); i++)
{
movie.Insert(0, Convert.ToString(GetLetter()));
}
movie.Insert(0, " ");
movie.Insert(0, Convert.ToString(GetYear()));
movie.Insert(0, " ");
for (int i = 0; i < GetNum(); i++)
{
movie.Insert(0, Convert.ToString(GetLetter()));
}
if (movieList.Contains(movie))
{
check = false;
}
else
{
movieList.Add(movie);
check = true;
}
} while (check == false);
Console.WriteLine(movieList[0]);
}
public static Random _random = new Random();
public static char GetLetter()
{
int num = _random.Next(0, 26);
char let = (char)('a' + num);
return let;
}
public static int GetNum()
{
int num = _random.Next(4, 11);
return num;
}
public static int GetYear()
{
int num = _random.Next(1920, 2020);
return num;
}
}
}
Strings are immutable, so calling the Insert() method on the movie string doesn't do anything to the current movie variable. Instead it returns the new string.
You are however better off changing the movie type from string to StringBuilder, which is a dynamically allocated buffer of characters, so your example becomes:
using System;
using System.Text;
using System.Collections.Generic;
namespace sotest
{
class Program
{
static void Main(string[] args)
{
Movies();
Console.ReadKey();
}
public static void Movies()
{
List<string> movieList = new List<string>();
bool check = false;
do
{
StringBuilder movie = new StringBuilder();
for (int i = 0; i < GetNum(); i++)
{
movie.Insert(0, Convert.ToString(GetLetter()));
}
movie.Insert(0, " ");
movie.Insert(0, Convert.ToString(GetYear()));
movie.Insert(0, " ");
for (int i = 0; i < GetNum(); i++)
{
movie.Insert(0, Convert.ToString(GetLetter()));
}
if (movieList.Contains(movie.ToString()))
{
check = false;
}
else
{
movieList.Add(movie.ToString());
check = true;
}
} while (check == false);
Console.WriteLine(movieList[0]);
}
public static Random _random = new Random();
public static char GetLetter()
{
int num = _random.Next(0, 26);
char let = (char)('a' + num);
return let;
}
public static int GetNum()
{
int num = _random.Next(4, 11);
return num;
}
public static int GetYear()
{
int num = _random.Next(1920, 2020);
return num;
}
}
}
The problem is that you are using movie.Insert incorrectly.
If you read the documentation for String.Insert it says
https://learn.microsoft.com/en-us/dotnet/api/system.string.insert?view=netframework-4.8
Returns a new string in which a specified string is inserted at a
specified index position in this instance
public string Insert (int startIndex, string value);
So it returns a new String, it does not amend the existing one. So you would need to do.
movie = movie.Insert(0, Convert.ToString(GetYear()));
However, I must also say that using String.Insert in this way is not the best approach.
You should instead look at using the StringBuilder class. It is very efficient when you want to amend strings (which are immutable objects).
You might want to read parts of this to help you understand. If you scroll down then it also suggests StringBuilder.
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/strings/
Insert() method is used to return a new string from the specified string at a specified index position. In your case, you are not capturing the updated string.
The best approach to solve this is through using StringBuilder object. Please note that StringBuilder object is much efficient rather than playing with immutable string.

How to recognize Event with onSensorChanged by comparing two float values

I want to read data from my Accelerometer Sensor and compare them if the first number of the float changes. I have some problem to unregister the listener or pause in order to compare and see if the average/Note has increased by a full Int for example "Note: 5.677" increases to "Note:6.234" then it supposed to be recognized as an event.
I have converted them into Ints so I can check if they are equal or not.
I already have tried to delay it with Thread.Sleep and pause but doesnt work.
Maybe because of Lock(_synlock) ?
public void OnSensorChanged(SensorEvent e)
{
lock (_syncLock)
{
avg = e.Values.Average();
_sensorTextView.Text = string.Format("x={0:f}, y={1:f}, z={2:f}", e.Values[0], e.Values[1], e.Values[2]);
_sensorTextView2.Text = string.Format("Note: {0}", avg);
note1 = e.Values.Average();
//Thread.Sleep(500);
//base.OnPause();
//_sensorManager.UnregisterListener(this);
//base.OnResume();
//_sensorManager.RegisterListener(this, _sensorManager.GetDefaultSensor(SensorType.Accelerometer), SensorDelay.Ui);
//_sensorTextView.Text = string.Format("x={0:f}, y={1:f}, z={2:f}", e.Values[0], e.Values[1], e.Values[2]);
//avg = e.Values.Average();
//_sensorTextView2.Text = string.Format("Note: {0}", avg);
//note2 = e.Values.Average();
}
int noteInt1 = Convert.ToInt32(note1);
int noteInt2 = Convert.ToInt32(note2);
//Thread.Sleep(2000); "zeige alle 2 sekunden an"
List<double> eventnumbers = new List<double> { };
if (noteInt1 != noteInt2)
{
avg = e.Values.Average();
//Console.WriteLine("bye");
_sensorTextView2.Text = string.Format("Note: {0}", avg);
//foreach(SensorEvent e){
eventnumbers.Add(new double()); //Value of avg is the value of the eventnumber element
eventnumbers.ForEach(Console.WriteLine);
}
}
UPDATE :
public void OnSensorChanged(SensorEvent e)
{
lock (_syncLock)
{
_sensorTextView.Text = string.Format("x={0:f}, y={1:f}, y={2:f}", e.Values[0], e.Values[1], e.Values[2]);
//_sensorTextView2.Text = string.Format("Note: {0}", e.Values.Average());
avg = e.Values.Average();
}
eventCounter();
}
public void eventCounter()
{
eventnumbers.Add(avg); //add number to our buffer
Console.WriteLine(avg);
eventnumbers.Add(avg+1); //adding a number different of our first one to see if the method works
Console.WriteLine(avg+1);
while (eventnumbers.Count >= 1) //as long as two elements included
{
for (int puffer = 0; puffer <= 10; puffer++) //buffer of 10 Elements
{
for (int i = 0; i < eventnumbers.Count; i++) //compare first number of our buffer
{
note1 = eventnumbers[i]; //remember value of first element
Console.WriteLine(note1);
Console.WriteLine("i ist:" + i);
for (int j = 1; j <= eventnumbers.Count; j++) //with the second number of our buffer
{
Console.WriteLine("j ist:" + j);
note2 = eventnumbers[j]; //remember value of second element
Console.WriteLine(note2);
}
}
while (eventnumbers.Count >= 1) //as long as two elements included
{
try
{
noteInt1 = Convert.ToInt32(note1); //double to Int
noteInt2 = Convert.ToInt32(note2);
if (noteInt1 != noteInt2) //we parse to int in order to compare if event has changed
{
_sensorTextView2.Text = string.Format("Note: {0}", avg); //if yes update our displaying mark/number
eventcounters.Add(avg); //add element to elementcounter
}
break; //
}
catch (System.ArgumentOutOfRangeException) //for the case if there are less than 2 elements to compare
{
eventcounters.ForEach(Console.WriteLine); //return all marks(numbers) from our eventcounter
}
break;
} break;
}
//throw new NotImplementedException();
}
eventnumbers.Clear();
}
My Problem is that I do not get another (different) value when I call e.Value.Average(). I need to do it outside the method and call onSensorChanged another time but i dont know how to do that since I need to create another event, right? thats why I have used e1 and e2 but I think I miss something with the initialization i guess.
This is how I have tried so far creating two events:
public class MainActivity : Activity, ISensorEventListener
{
static readonly object _syncLock = new Object();
SensorManager _sensorManager;
TextView _sensorTextView;
TextView _sensorTextView2;
double note1;
double note2;
double avg;
SensorEvent e1;
SensorEvent e2;
my one create():
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.activity_main);
_sensorManager = (SensorManager)GetSystemService(SensorService);
_sensorTextView = FindViewById<TextView>(Resource.Id.accelerometer_text);
_sensorTextView2 = FindViewById<TextView>(Resource.Id.accelerometer_note);
e1 = (SensorEvent)GetSystemService(ISensorEventListener);
e2 = (SensorEvent)GetSystemService(ISensorEventListener);
displayMark();
ISensorEventListener is marked a wrong btw
public void displayMark()
{
OnSensorChanged(e1);
note1 = e1.Values.Average();
OnSensorChanged(e2);
note2 = e2.Values.Average();
int noteInt1 = Convert.ToInt32(note1);
int noteInt2 = Convert.ToInt32(note2);
Console.WriteLine(noteInt1);
Console.WriteLine(noteInt2);
List<double> eventnumbers = new List<double> { };
if (noteInt1 != noteInt2)
{
avg = e2.Values.Average();
Console.WriteLine("bye");
_sensorTextView2.Text = string.Format("Note: {0}", avg);
//foreach(SensorEvent e){
eventnumbers.Add(new double()); //Value of avg is the value of the eventnumber element
}
eventnumbers.ForEach(Console.WriteLine);
I'm just going to deal with the general approach here. Rather than trying to wait in an event for some new data I would use the events to record a value and then compare the new one to the last one. So outside the function would be a variable something like:
private int previousValue;
Then when the function is called it compares the 'new' value to this previous one:
public void OnSensorChanged(SensorEvent e)
{
// Can't tell if this is required with information available
lock (_syncLock)
{
// Capture the 'new' data to a local variable
var newValue = e.Values.Average();
if (newValue != previousValue)
{
// Value has changed by required amount so do something here
}
// Update the previous so next we we use this as our reference value
previousValue = newValue;
}
This isn't a full solution but should be a better starting point for developing one.

C# Console App -- Trying to access a list from else statement

This is for a data structures and algorithms class. We're just starting out with bubble sort. The instructions were to generate random, unique integers and sort them using the sorting technique of the lecture. It will be required to add different sorting techniques as well.
To generate the list of random numbers, I generated a list and then shuffled the list using the fisher-yates algorithm. So I have my unique, sorted list of whatever size I choose.
I'm getting stuck because after I generate the random list, I am having problems accessing the list to run it through BubbleSort.
Is there any way I can do this?
class Algorithms
{
static void Main(string[] args)
{
string response = "";
//Main Console Menu
while (response != "exit")
{
Console.WriteLine("Type help for list of commands");
response = Console.ReadLine();
//List<int> toSort = new List<int>();
if (response.StartsWith("exit"))
{
Environment.Exit(0);
}
else if (response.ToLower().StartsWith("help"))
{
Help(response);
}
else if (response.ToLower().StartsWith("generate"))
{
// Shuffle(Generate(response));
// have been using the line above but adding next line for
//an idea of my problem
List<int> toSort = Shuffle(Generate(response));
}
else if (response.ToLower().StartsWith("bubble"))
{
//This doesn't work and I'm trying to figure out how it can
BubbleSort(toSort);
}
}
}
//Displays help information
public static void Help(string input)
{
Console.WriteLine("\ngenerate <integer> -- Generates a data set of intended amount of integers\n"+
"algorithm <algorithm type> -- Choose which algorithm to sort data\nexit -- exit application\n" );
}
//Generates List of integers from 0 to number choosen by user
public static List<int> Generate(string size)
{
int cutString = size.Length - 9;
string sizeSubset = size.Substring(9, cutString);
List<int> numGen = new List<int>();
int dataSetSize = Convert.ToInt32(sizeSubset);
for(int i = 0; i <= dataSetSize; i++)
{
numGen.Add(i);
// Console.WriteLine(numGen[i]);
}
return numGen;
}
//Use Fisher-Yates algorithm to shuffle the list.
static Random randomize = new Random();
public static List<int> Shuffle(List<int>makeRandom)
{
List<int> shuffled = new List<int>();
int n = makeRandom.Count;
while (n > 1)
{
n--;
int k = randomize.Next(n + 1);
int value = makeRandom[k];
makeRandom[k] = makeRandom[n];
makeRandom[n] = value;
shuffled.Add(value);
Console.WriteLine(value);
}
return shuffled;
}
public static void BubbleSort(List<int>input)
{
for(int i = 0; i <= input.Count; i++)
{
for (int j = 0; j <= (input.Count - 1); j++)
{
if (input[j] > input[j + 1])
{
int temp = input[j];
input[j] = input[j + 1];
input[j + 1] = temp;
Console.WriteLine("hello");
}
}
}
}
}
}
You defined list in scope of else if (response.ToLower().StartsWith("generate")) code block, so it is not accessible outside of that block. Move declaration to Main method scope, like this:
static void Main(string[] args)
{
string response = "";
//define your list here.
List<int> toSort = new List<int>();
//Main Console Menu
while (response != "exit")
{
Console.WriteLine("Type help for list of commands");
response = Console.ReadLine();
if (response.StartsWith("exit"))
{
Environment.Exit(0);
}
else if (response.ToLower().StartsWith("help"))
{
Help(response);
}
else if (response.ToLower().StartsWith("generate"))
{
toSort = Shuffle(Generate(response));
}
else if (response.ToLower().StartsWith("bubble"))
{
List<int> sortedList = BubbleSort(toSort);
}
}
}

Arraylist.add() is overwriting all the values in the Arraylist built by a loop in c#

Arraylist.add() is overwriting all the previous values in the Arraylist built by a loop in c#. The code is:
public ArrayList MakeList(int size, int iterations)
{
ArrayList myList = new ArrayList(iterations);
for (int run = 0; run < iterations; run++)
{
byte[] _byteArray = new byte[size];
bool success = false;
while (!success)
{
//Some Operations
if(condition)
success = true;
else
continue;
if(success)
break;
}
myList .Add(_byteArray );
}
return myList;
}
The above loop always overwriting the values in the List with the latest byte array. Kindly help me to resolve this.
Karthick initially I thought it to be an issue of deep copy or shallow copy but as long as you are initializing the byte array inside the for loop it should work perfectly. I tried following sample code at my end and it works perfectly fine when function MakeList is about to return. Three byte arrays pointed by myList contain 00,01,11 as I've inserted them and there is no overwriting as suggested by you. I've hardcoded few parameters for quick output:
public class Program
{
public static void Main(string[] args)
{
var col = new ColTest();
col.MakeList();
}
}
public class ColTest
{
public ArrayList MakeList()
{
var capacity = 3;
ArrayList myList = new ArrayList(capacity);
int size = 2;
for (int run = 0; run < capacity; run++)
{
byte[] _byteArray = new byte[size];
if (run == 0)
{
_byteArray[0] = 0;
_byteArray[1] = 0;
}
else if (run == 1)
{
_byteArray[0] = 0;
_byteArray[1] = 1;
}
else if (run == 2)
{
_byteArray[0] = 1;
_byteArray[1] = 1;
}
myList.Add(_byteArray);
}
return myList;
}
}
Hope this helps!

Ideas to manage IP and Ports in Key/Value format?

I'm looking for a good and fast way to manage IP addresses and ports in a file. Sort of a DB Table that has 2 columns: IP and Port, but in a file, without using a DB.
It has to support adding, deleting and updating. I don't care from concurrency.
Below, some come to complete your task. I tried to go strictly to the point, so maybe something is missing.
I'd to create a "Record" class, to keep ip/port pairs
class Record : IPEndPoint, IComparable<Record>
{
internal long Offset { get; set; }
public bool Deleted { get; internal set; }
public Record() : base(0, 0)
{
Offset = -1;
Deleted = false;
}
public int CompareTo(Record other)
{
if (this.Address == other.Address && this.Address == other.Address )
return 0;
else if (this.Address == other.Address)
return this.Port.CompareTo(other.Port);
else
return
BitConverter.ToInt32(this.Address.GetAddressBytes(), 0).CompareTo(
BitConverter.ToInt32(other.Address.GetAddressBytes(), 0));
}
}
class RecordComparer : IComparer<Record>
{
public int Compare(Record x, Record y)
{
return x.CompareTo(y);
}
}
...And a "DatabaseFile" class to manage datafile interaction.
class DatabaseFile : IDisposable
{
private FileStream file;
private static int RecordSize = 7;
private static byte[] Deleted = new byte[] { 42 };
private static byte[] Undeleted = new byte[] { 32 };
public DatabaseFile(string filename)
{
file = new FileStream(filename,
FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
}
public IEnumerable<Record> Locate(Predicate<Record> record)
{
file.Seek(0, SeekOrigin.Begin);
while (file.Position < file.Length)
{
long offset = file.Position;
byte[] buffer = new byte[DatabaseFile.RecordSize];
file.Read(buffer, 0, DatabaseFile.RecordSize);
Record current = Build(offset, buffer);
if (record.Invoke(current))
yield return current;
}
}
public void Append(Record record)
{
// should I look for duplicated values? i dunno
file.Seek(0, SeekOrigin.End);
record.Deleted = false;
record.Offset = file.Position;
Write(record);
}
public void Delete(Record record)
{
if (record.Offset == -1) return;
file.Seek(record.Offset, SeekOrigin.Begin);
record.Deleted = true;
Write(record);
}
public void Update(Record record)
{
if (record.Offset == -1)
{
Append(record);
}
else
{
file.Seek(record.Offset, SeekOrigin.Begin);
Write(record);
}
}
private void Write(Record record)
{
file.Write(GetBytes(record), 0, DatabaseFile.RecordSize);
}
private Record Build(long offset, byte[] data)
{
byte[] ipAddress = new byte[4];
Array.Copy(data, 1, ipAddress, 0, ipAddress.Length);
return new Record
{
Offset = offset,
Deleted = (data[0] == DatabaseFile.Deleted[0]),
Address = new IPAddress(ipAddress),
Port = BitConverter.ToInt16(data, 5)
};
}
private byte[] GetBytes(Record record)
{
byte[] returnValue = new byte[DatabaseFile.RecordSize];
Array.Copy(
record.Deleted ? DatabaseFile.Deleted : DatabaseFile.Undeleted, 0,
returnValue, 0, 1);
Array.Copy(record.Address.GetAddressBytes(), 0,
returnValue, 1, 4);
Array.Copy(BitConverter.GetBytes(record.Port), 0,
returnValue, 5, 2);
return returnValue;
}
public void Pack()
{
long freeBytes = 0;
byte[] buffer = new byte[RecordSize];
Queue<long> deletes = new Queue<long>();
file.Seek(0, SeekOrigin.Begin);
while (file.Position < file.Length)
{
long offset = file.Position;
file.Read(buffer, 0, RecordSize);
if (buffer[0] == Deleted[0])
{
deletes.Enqueue(offset);
freeBytes += RecordSize;
}
else
{
if (deletes.Count > 0)
{
deletes.Enqueue(offset);
file.Seek(deletes.Dequeue(), SeekOrigin.Begin);
file.Write(buffer, 0, RecordSize);
file.Seek(offset + RecordSize, SeekOrigin.Begin);
}
}
}
file.SetLength(file.Length - freeBytes);
}
public void Sort()
{
int offset = -RecordSize; // lazy method
List<Record> records = this.Locate(r => true).ToList();
records.Sort(new RecordComparer());
foreach (Record record in records)
{
record.Offset = offset += RecordSize;
Update(record);
}
}
public void Dispose()
{
if (file != null)
file.Close();
}
}
Below, a working example:
static void Main(string[] args)
{
List<IPEndPoint> endPoints = new List<IPEndPoint>(
new IPEndPoint[]{
new IPEndPoint(IPAddress.Parse("127.0.0.1"), 80),
new IPEndPoint(IPAddress.Parse("69.59.196.211"), 80),
new IPEndPoint(IPAddress.Parse("74.125.45.100"), 80)
});
using (DatabaseFile dbf = new DatabaseFile("iptable.txt"))
{
foreach (IPEndPoint endPoint in endPoints)
dbf.Append(new Record {
Address = endPoint.Address,
Port = endPoint.Port });
Record stackOverflow = dbf.Locate(r =>
Dns.GetHostEntry(r.Address)
.HostName.Equals("stackoverflow.com")).FirstOrDefault();
if (stackOverflow != null)
dbf.Delete(stackOverflow);
Record google = dbf.Locate(r =>
r.Address.ToString() == "74.125.45.100").First();
google.Port = 443;
dbf.Update(google);
foreach(Record http in dbf.Locate(r =>
!r.Deleted && r.Port == 80))
Console.WriteLine(http.ToString());
}
Console.ReadLine();
}
dBase III, I miss you.
Well, that was fun, thank you!
EDIT 1: Added Pack() and lazy Sort() code;
EDIT 2: Added missing IComparable/IComparer implementation
I personally will go for
192.100.10.1:500:20-21
192.100.10.2:27015-27016:80
Where the first is the Ip and every thing after the : is a port, We can also represent a range by - and if we want to be very crazy about it we can introduce a u which will represent the port type UDP or TCP for example:
192.100.10.2:27015-27016:80:90u
And explode() would work for the above quite easily.
When talking about Inserting Deleting and updating.. We can simply create a class structure such as
struct port{
int portnum;
char type;
port(int portnum = 0, char type = 't'){
this.portnum = portnum; this.type = type;
}
}
class Ip{
public:
string Ip_str;
list <port> prt;
}
And then you can have the main to look like
int main(){
list<Ip> Ips;
//Read the list from file and update the list.
//Sort delete update the list
//Rewrite the list back into file in the order mentioned obove
return 0;
}
The easiest way is probably to create a small class that contains your IP and port
class IpAddress
{
public string IP;
public int port;
}
and then create a list<IpAddress> of them. You can then use XML Serialization and Deserialization to read to and write from a file your list.
The .NET BCL does not offer what you are looking for as you want to query against a file without loading it into memory first and support add/remove. So you'd either have to roll your own embedded database or you could simply use something like SQLite http://www.sqlite.org/
IP and Port is a one to many relationship. I would consider something like this
\t192.168.1.1\r\n25\r\n26\r\n\t192.168.1.2\r\n2\r\n80\r\n110
where \t is a tab and \r\n is a carriage return followed by a newline
So when you parse, if you hit a tab character, you know everything that's in that line from there to the newline is an IP address, then everything in between the next newlines is a port number for that IP address until you hit a tab, in which case you're on a new IP address. That's simple and fast but not as human readable.
this has nothing to do with IP and ports.. the problem is that, as far as i know, windows does not allow to INSERT or remove bytes in/from the middle of a file..

Categories

Resources