I'm trying to remove all CRLF characters from the string dataFromClient in the C# code bellow. All of the following attempts have failed so far and I'd be very thankful for your help:
edit:
The problem is that whenever the Console.WriteLine(dataFromClient) method is called, the string prints but looks like this: "\vposition?:X\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0....." I want the output to only be "position?:X". But have not been able to trim the "\0" from the string.
This code is my first attempt at setting up a simple server to accept a connection form a third party software. Requests are made from the client, then this server parses the request to commands that a motorized Cartesian stage understands.
Bellow is the code from the server portion/ class of the console app.
Posts with suggestions I already tried:
Removing carriage return and new-line from the end of a string in c#
Serial communication and CRLF C#
How to WriteAllLines in C# without CRLF
Remove a character from a string
String Trim Spaces doesn't work
Here is the code:
using System;
using System.Net;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace autotile_V001
{
public class Myserver
{
int MyServerPort;
bool go = true;
int requestCount = 0;
string dataFromClient;
string serverResponse;
IPAddress ipAddr = IPAddress.Loopback;
public string process(string s)
{
int len = s.Length;
int current = 0;
StringBuilder sb = new StringBuilder(len);
while (current < len - 1)
{
if ((s[current] == ' ' && s[current + 1] == ' '))
{
break;
}
else
{
sb.Append(s[current]);
}
current++;
}
return sb.ToString();
}
public void StartMyServer()
{
TcpListener serverSocket = new TcpListener(ipAddr, MyServerPort);
TcpClient clientSocket = default(TcpClient);
serverSocket.Start();
Console.WriteLine(" >> Server Started");
clientSocket = serverSocket.AcceptTcpClient();
Console.WriteLine(" >> Accepted connection from client");
requestCount = 0;
while ((go))
{
try
{
requestCount++;
NetworkStream networkStream = clientSocket.GetStream();
byte[] bytesFrom = new byte[(int)clientSocket.ReceiveBufferSize];
networkStream.Read(bytesFrom, 0, (int)clientSocket.ReceiveBufferSize);
dataFromClient = System.Text.Encoding.ASCII.GetString(bytesFrom);
Console.WriteLine(" >> Data from client - {0}", (String.Join("\n", dataFromClient)).Trim());
serverResponse = Console.ReadLine();
Byte[] sendBytes = Encoding.ASCII.GetBytes(serverResponse);
networkStream.Write(sendBytes, 0, sendBytes.Length);
networkStream.Flush();
Console.WriteLine(" >> " + serverResponse);
go = true;
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
go = false;
}
}
}
public Myserver(int someData)
{
MyServerPort = someData;
}
}
}
Trim() just removes leading and trailing whitespace - not whitespace within a string.
You'll need to use Replace to remove out unwanted characters or strings from inside a string. In the case above, any trialing non-white space character (which might not be visible, e.g. 0x0) in the byte stream will cause the call to Trim not to work.
var someString = "FOO\r\n\r\n\0";
var strippedTrim = someString.Trim(); // Fail - "FOO\r\n\r\n\0"
var strippedReplace = someString.Replace("\r\n", ""); // "FOO\0"
// .Replace() any other unwanted white space, e.g. "\t"
Noted however that Trim() will still remove a trailing naked '\n' (as opposed to Windows CRLF), so it isn't the String.Join("\n" causing the bug.
Edit
Just to clarify the string.Join - string.Join when used on a single string is redundant / has no effect (neither does it treat the string as an array of single character strings).
var join = string.Join("x", "FOO\r\n\r\n").Trim(); // Works - "FOO"
Related
I am new to c#. I have text file with data in it but I want to read particular block line data.
Here address can occur multiple times in text file.
Something here...
... ... ...
interface "system"
address 10.4.1.10/32
no shutdown
exit
something here...
... ... ...
address 101.4.1.11/32
but i want to capture within this
interface "system"
address 10.4.1.10/32
no shutdown
exit
I want to capture this ip from the block:
10.4.1.10
I tried this code:
int counter = 0;
string line;
// Read the file and display it line by line.
System.IO.StreamReader file = new System.IO.StreamReader("c:\\test.txt");
while((line = file.ReadLine()) != null)
{
Console.WriteLine (line);
counter++;
}
file.Close();
// Suspend the screen.
Console.ReadLine();
Expected Output:
my expected output is to capture the ip address from that block ie.10.4.1.10
that ip is inside "interface system" block.. that makes that address as unique.. as there can be many ips with keyword address. So i want to take address which is inside interface system block.
Please let me know how i can capture particular string from the block.
Regular Expressions are perfectly suited to handle this type of "problem". The following console app demonstrates how to use Regex to extract the desired IP address from the targeted string block.
private static readonly string IPV4_PATTERN = "[0-9./]";
private static readonly string IPV4_IPV6_PATTERN = "[A-Z0-9:./]";
static void Main(string[] args)
{
TestSearchFile();
}
private static string ParseIpWithRegex(string textToSearch, string startBlock, string endBlock)
{
var pattern = $#"{startBlock}\D*\s*({IPV4_IPV6_PATTERN}+).*{endBlock}";
var ms = Regex.Match(textToSearch, pattern, RegexOptions.Singleline | RegexOptions.IgnoreCase);
if (ms.Groups.TryGetValue("1", out var g))
{
return g.Value;
}
return string.Empty;
}
private static void TestSearchFile()
{
var sep = Environment.NewLine;
var ipAddress6 = "2001:db8:85a3:8d3:1319:8a2e:370:7348";
var ipAddress4 = "10.4.1.10/32";
var t = "Something here..." + sep;
t += "... ... ... " + sep;
t += "interface \"system\"" + sep;
t += "address " + ipAddress4 + sep;
t += "no shutdown" + sep;
t += "exit" + sep;
t += "something here..." + sep;
t += "address 101.4.1.11/32" + sep;
t += "... ... ... " + sep;
var startBlock = "interface \"system\"";
var endBlock = "exit";
var ip = ParseIpWithRegex(t, startBlock, endBlock);
Console.WriteLine($"IP: {ip}");
}
I've included two IP address patterns IPV4_PATTERN for IPV4 only as well as IPV4_IPV6_PATTERN for both IPV4 and IPV6. Select the one you feel is most appropriate. Although the IPV4_IPV6_PATTERN would apply to both IP versions I believe it improves performance slight when the search is narrowed by using the narrowest pattern.
Don't forget to import the Regex reference:
using System.Text.RegularExpressions;
**Code Explained**
The method "ParseIpWithRegex" uses a Regex pattern constructed by using the string that signifies the start of the targeted block and the string that signifies the end of that block. Nestled within that pattern is the regular expressions class definition that defines the IP address pattern we wish to isolate as a group.
$#"{startBlock}\D*\s*({IPV4_IPV6_PATTERN}+).*{endBlock}";
It should be noted that the curly brackets are just for string interpolation and have (in this case) nothing to do with the actual regular expression!
After the "startBlock" we see "\D*". This means that after the "startBlock" include in the search all non-numeric characters (where the "star" indicates to expect zero to infinitely many). Then we see "\s*" which means to include all white space (including new line characters since I included RegexOptions.Singleline).
The IP address pattern is in brackets "()" which instructs Regex to create groups. In this case, behind the IP address pattern (in the above code example IPV4_IPV6_PATTERN) there is a "+" symbol. This indicates that there MUST be at least one of the characters that is in the IP address Regex class definition in order to be considered a "match".
After that we see ".*" in front of the "endBlock". This means to look for any character--including the "new line" character (zero to infinitely many) in from of the "endBlock" string.
If you have any questions, please leave a comment.
EDIT
From your button onclick method you will call SearchFileForIp. You will need to change myTextBox to match your code.
You should also decide whether you will be searching IPV4 or both IPV4 and IPV6 and select the appropriate variable IPV4_PATTERN or IPV4_IPV6_PATTERN.
private void SearchFileForIp()
{
var fileName = "c:\\test.txt";
using var sr = new StreamReader(fileName);
string fileContent = sr.ReadToEnd();
var startBlock = "interface \"system\"";
var endBlock = "exit";
var ip = ParseForIpRegex(fileContent, startBlock, endBlock);
myTextBox.Text = ip; //Change this to match your code
}
private readonly string IPV4_PATTERN = "[0-9./]";
private readonly string IPV4_IPV6_PATTERN = "[A-Z0-9:./]";
private string ParseForIpRegex(string textToSearch, string startBlock, string endBlock)
{
var pattern = $#"{startBlock}\D*\s*({IPV4_PATTERN}+).*{endBlock}";
var ms = Regex.Match(textToSearch, pattern, RegexOptions.Singleline | RegexOptions.IgnoreCase);
if(ms.Groups.Count > 0)
{
return ms.Groups[1].Value;
}
//For .Net Core apps
//if (ms.Groups.TryGetValue("1", out var g))
//{
// return g.Value;
//}
return string.Empty;
}
In addition to the 2 answers with Regex solutions, If address line comes always after interace "system", than a simple for loop can do the job.
interface "system"
address 10.4.1.10/32
no shutdown
exit
So We go thorugh file lines and check if line is interace "system" than take the next value and parse it to string of ip address.
public static string GetIpAddressFromFile(string fileName, string startLine)
{
var lines = File.ReadAllLines(fileName);
var ipAddress = string.Empty;
for (var i = 0; i < lines.Length; i++)
{
var line = lines[i].Trim();
if (line != startLine) continue;
var addressLine = lines[i + 1].Trim().Replace("address", "");
ipAddress = addressLine.Substring(0, addressLine.IndexOf("/", StringComparison.Ordinal));
break;
}
return ipAddress.Trim();
}
Lets assume you that your file is inconsistent and address does not comes first after interface "system"
interface "system"
...
address 10.4.1.10/32
no shutdown
exit
So in this case we put all lines between interface "system" and exit in list of strings, Or dictionary and fetch the address key.
public static string GetIpAddressFromFile(string fileName, string startLine, string endLine)
{
var lines = File.ReadAllLines(fileName);
var ipAddress = string.Empty;
var state = false;
var results = new Dictionary<string, string>();
foreach (var t in lines)
{
var line = t.Trim();
if (line == startLine)
state = true;
if (line == endLine)
state = false;
if (!state) continue;
var s = line.Split(" ");
results.TryAdd(s[0], s[1]);
}
var result = results.GetValueOrDefault("address");
if (result != null)
{
ipAddress = result.Substring(0, result.IndexOf("/", StringComparison.Ordinal));
}
return ipAddress;
}
Usage:
var startLine = "interface \"system\"";
var endLine = "exit";
var ip = GetIpAddressFromFile(#"File.txt", startLine);
//Or
var ip = GetIpAddressFromFile1(#"File.txt", startLine, endLine);
Both methods are tested with your given example and return:
10.4.1.10
If the start of the block and the end of the block are well defined, in order to find the block you can simply:
Search for the start of the block
Do something with the lines until the end of the block
string line;
System.IO.StreamReader file = new System.IO.StreamReader("c:\\test.txt");
while((line = file.ReadLine()) != null && !line.Equals(START_OF_BLOCK)); // 1.
while((line = file.ReadLine()) != null && !line.Equals(END_OF_BLOCK)) // 2.
{
// do something with the lines
}
file.Close();
Updated answer after edited question:
In order to "extract" the string in a form of an IP address inside the block, you could, for example, use Regular expressions with a .NET Regex class, with previously finding the needed block:
Search for the start of the block
Search for the line inside the block which contains "address"
Extract the IP address from the line using Regexp.Match()
string line;
System.IO.StreamReader file = new System.IO.StreamReader("c:\\test.txt");
string pat = #"\b(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\b";
System.Text.RegularExpressions.Regex reg = new System.Text.RegularExpressions.Regex(pat);
while ((line = Console.ReadLine()) != null && !line.Equals(START_OF_BLOCK)); // 1.
while ((line = Console.ReadLine()) != null && !line.Equals(END_OF_BLOCK)) // 2.
{
if (line.Contains("address"))
{
System.Text.RegularExpressions.Match ip = reg.Match(line);
Console.WriteLine(ip);
break; // break if you are sure there's only one ip in that block
}
}
file.Close();
Here is simple LINQ for that:
var textData = File.ReadAllLines("Path goes here");
var address = string.Join("", textData
.SkipWhile(x => !x.Trim().StartsWith($"interface \"system\""))
.SkipWhile(x => !x.Trim().StartsWith($"address"))
.Take(1)).Split("address")[1].Trim();
SkipWhile goes trough string array until it finds line which starts
like: "interface \"system\"".
Second SkipWhile goes trough part after "interface \"system\"" string until
it finds line which starts like: "address".
Then you Take(1) matching line and create string out of it.
Then you use Split to create new array which contains address text
and ip address.
After that you simply take last part of the array.
I need to write and read data from serial port to my device. I've test certain approach where at first, I'm receiving the data using SerialDataReceivedEventArgs and I feel it is hard to read the port where I need to define the command that send where as the command is almost 200 commands.
My first approach is using:-
private void ObjCom_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
if (!ObjCom.IsOpen) return;
byte[] data = new byte[ObjCom.BytesToRead];
ObjCom.Read(data, 0, data.Length);
RaiseEventMsg("Buffer String: " + BitConverter.ToString(data).Replace("-", " "));
}
The RaiseEventMsg is a delegate event to pass current information to Main UI. The second approach is:-
private long lngTickCount = Convert.ToInt64(1000L);
public void StartWriteToPort()
{
byte[] Cmd = null;
string strCmd = string.Empty;
string strMsg = null;
bool bCont = true;
long lngCurrent = 0;
long lngNow = 0;
try
{
RaiseEventMsg("Start Write To Port");
ObjCom.DiscardOutBuffer();
ObjCom.DiscardInBuffer();
GetFullCommandByte(ref Cmd, Convert.ToByte(123)); // Referencing Cmd with return and pass Command List(various set of command)
ObjCom.Write(Cmd, 0, Cmd.Length);
strCmd = ByteArrayToString(Cmd); // Convert byte array to Hex string
RaiseEventMsg("Send: " + strCmd);
bool bTimeout = false;
lngCurrent = DateTime.Now.Ticks;
while (!bTimeout)
{
lngNow = DateTime.Now.Ticks;
if (lngNow > (lngCurrent + (3 * lngTickCount)))
{
bTimeout = true;
break;
}
}
lngCurrent = DateTime.Now.Ticks;
while (ObjCom.BytesToRead <= 0)
{
lngNow = DateTime.Now.Ticks;
if (lngNow > (lngCurrent + (1000 * lngTickCount)))
{
bCont = false;
break;
}
}
if (!bCont)
{
strMsg = "Error - Timeout Hit";
RaiseEventMsg(strMsg);
return;
}
int Idx = 0;
string strASCIIFull = string.Empty;
if ((ObjCom.BytesToRead > 0) & (bCont == true))
{
while (ObjCom.BytesToRead > 0)
{
var strASCII = ObjCom.ReadByte();
var TmpHex = System.Convert.ToString(strASCII, 16).ToUpper();
if (TmpHex.Length == 1)
{
strASCIIFull += (" 0" + TmpHex);
}
else
{
strASCIIFull += (" " + TmpHex);
}
lngCurrent = DateTime.Now.Ticks;
while (ObjCom.BytesToRead <= 0)
{
lngNow = DateTime.Now.Ticks;
if (lngNow > (lngCurrent + (2 * lngTickCount)))
{
bCont = false;
break;
}
}
Idx += 1;
}
}
RaiseEventMsg("Recv: " + strASCIIFull);
}
catch (System.Exception ex)
{
string error = $"Exception on StartWriteToPort. Message: {ex.Message}. StackTrace: {ex.StackTrace}";
}
}
Problem on second approach is when I call this function for second time, the timeout will hit . But for Serial event, it does not have the problem, the protocol for timeout is set to 1 seconds. My device currently connected using USB without converter. The input cable to device is type B port (like standard printer port).
Is the any other way to read directly from port or any improvement on current code?
You need to learn how to layer your code. At the moment you have one long function that tries to do everything.
If you had several smaller functions that did specific things like reading or writing a chunk of information then it would make what you are trying to do simpler.
For example, serial communications generally have some sort of protocol that encapsulates how the packets of information are stored. Say the protocol was "", then you know every packet starts with an STX byte (0x01), a length byte, which tells you how many bytes are in the section, and there must be an ETX byte (0x02) at the end. You could write a function that would return an array of bytes that are just the because the function would interpret the stream and extract the relevant parts.
Then it might be as simple as:
var packet1 = ReadPacket();
WritePacket(outputData);
var packet2 = ReadPacket();
I use HUAWEI USB stick modem and code below to send SMS successfully but under 140 of length (see the code pls -- double lenMes = textsms.Length / 2;).
But nowdays I see the really big SMS messages.
So I am wondering what's wrong with AT commnds or may me hardware is old so I cannot send big SMS.
Please any clue?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO.Ports;
namespace sendSMSPDU
{
class Program
{
static SerialPort port;
static void Main(string[] args)
{
port = new SerialPort();
Console.WriteLine("Sending SMS");
OpenPort();
bool result;
result = sendSMS("Some text that less 140 is gonna sending OK", " +75434355544");
if (result == true)
{
Console.WriteLine("OK");
}
else
{
Console.WriteLine("ERROR");
}
Console.ReadLine();
port.Close();
}
private static bool sendSMS(string textsms, string telnumber)
{
if (!port.IsOpen) return false;
try
{
System.Threading.Thread.Sleep(500);
port.WriteLine("AT\r\n");
System.Threading.Thread.Sleep(500);
port.Write("AT+CMGF=0\r\n");
System.Threading.Thread.Sleep(500);
}
catch
{
return false;
}
try
{
telnumber = telnumber.Replace("-", "").Replace(" ", "").Replace("+", "");
telnumber = "01" + "00" + telnumber.Length.ToString("X2") + "91" + EncodePhoneNumber(telnumber);
textsms = StringToUCS2(textsms);
string leninByte = (textsms.Length / 2).ToString("X2");
textsms = telnumber + "00" + "08" + leninByte + textsms;
double lenMes = textsms.Length / 2;
if (lenMes < 140) // It sends OK
{
port.Write("AT+CMGS=" + (Math.Ceiling(lenMes)).ToString() + "\r\n");
System.Threading.Thread.Sleep(500);
textsms = "00" + textsms;
port.Write(textsms + char.ConvertFromUtf32(26) + "\r\n");
System.Threading.Thread.Sleep(500);
}
else
{
return false;
}
}
catch
{
return false;
}
try
{
string recievedData;
recievedData = port.ReadExisting();
if (recievedData.Contains("ERROR"))
{
return false;
}
}
catch { }
return true;
}
private static void OpenPort()
{
port.BaudRate = 9600;
port.DataBits = 7;
port.StopBits = StopBits.One;
port.Parity = Parity.Odd;
port.ReadTimeout = 500;
port.WriteTimeout = 500;
//port.Handshake = Handshake.RequestToSend;
//port.DtrEnable = true;
//port.RtsEnable = true;
//port.NewLine = Environment.NewLine;
port.Encoding = Encoding.GetEncoding("windows-1252");
port.PortName = "COM7";
if (port.IsOpen)
port.Close();
try
{
port.Open();
}
catch { }
}
public static string EncodePhoneNumber(string PhoneNumber)
{
string result = "";
if ((PhoneNumber.Length % 2) > 0) PhoneNumber += "F";
int i = 0;
while (i < PhoneNumber.Length)
{
result += PhoneNumber[i + 1].ToString() + PhoneNumber[i].ToString();
i += 2;
}
return result.Trim();
}
public static string StringToUCS2(string str)
{
UnicodeEncoding ue = new UnicodeEncoding();
byte[] ucs2 = ue.GetBytes(str);
int i = 0;
while (i < ucs2.Length)
{
byte b = ucs2[i + 1];
ucs2[i + 1] = ucs2[i];
ucs2[i] = b;
i += 2;
}
return BitConverter.ToString(ucs2).Replace("-", "");
}
}
}
Single SMS message is limited to 160 (or 152 in PDU mode) symbols in GSM-7 encoding. More than that, if there is any symbol not listed here you need to use UCS-2 encoding and your messages now limit to 67 symbols. If you need to send longer messages, you are welcome to the "bright and shiny world" of SMS PDU mode.
So sending a long sms is as easy as:
Split it to parts of 67 (or 152) symbols;
Convert this parts to UCS-2 or GSM-7 encoding;
Transform them to PDU messages;
Send them sequentially with use of additional AT-command (AT+CMGF=0)
Edit
The one who designed a PDU format is a true evil person. It is really mind breaking thing and I don't want to write a convertion code, sorry. But, I can point you with this stub:
protected void SendMessage(string phoneNumber, string message)
{
const char CR = '\r'; // "Carage Return"
const char CtrlZ = (char)26; // Ctrl+Z character
var header = GeneratePDUHeader(phoneNumber);
foreach (var messagePart in SplitSMSMessage(message))
{
SendToCOM("AT+CMGF=0" + CR);
SendToCOM("AT+CMGS=42" + CR);
SendToCOM($"{header}{messagePart}" + CtrlZ);
}
}
// should return something like "0041000B910000000000F000088C"
protected string GeneratePDUHeader(string phoneNumber) { }
// split long message to parts
protected IEnumerable<string> SplitSMSMessage(string message)
{
var useUCSEncoding = IsUCSEncodingNeeded(message);
var partLength = useUCSEncoding ? 67 : 152;
var messageParts = Enumerable.Range(0, message.Length / partLength)
.Select(i => message.Substring(i * partLength, partLength))
.ToArray();
var referenceNumber = $"{GenerateReferenceNumber():X2}"; // convert to HEX, i.e. "01"
var totalMessagesCount = $"{messageParts.Length:X2}"; // convert to HEX, i.e. "01"
var udhBase = $"050003{referenceNumber}{totalMessagesCount}";
var messageNumber = (char)0;
foreach (var messagePart in messageParts)
{
var udh = $"{udhBase}{++messageNumber}";
var messagePartText = useUCSEncoding ? StringToUCS(messagePart) : StringToGSM7(messagePart);
yield return $"{udh}{messagePartText}";
}
}
private void SendToCOM(string message) { } // writes message to COM port
private bool IsUCSEncodingNeeded(string message) { } // determine if UCS-2 convert is required
private char GenerateReferenceNumber() { } // random number 0-255
private string StringToUCS(string message) { } // convert string to UCS encoding
private string StringToGSM7(string message) { } // convert string to GSM7 encoding (don't forget about padding!)
You may also find this links are useful:
https://en.wikipedia.org/wiki/Concatenated_SMS
https://www.developershome.com/sms/cmgsCommand4.asp
The best answer to my question is here
How to concat long SMS in GSMComm Library?
https://github.com/welly87/GSMComm
https://www.nuget.org/packages/GSMComm/
It work fine with my HUAWEI GSM modem! WOW!
I have a really big txt file, (call it input.txt). Most of the information is unnecessary for me, but there are a lot of iD-s, which are between the id= and ampstrings.
I want to write every id to a new txt file, (output.txt) , where every iD is in a new line.
How can I manage this?
https://pastebin.com/5tqAiPUi -- Sample txt
Desired output:
1839708603
1845432669
1850285729
100000000530931
100000011404225
You can try regular expressions:
using System.Text.RegularExpressions;
using System.Linq;
...
string text = ...;
string[] ids = Regex
.Matches(text, "(?:id=)(?<value>[0-9]+)(?:&)")
.OfType<Match>()
.Select(match => match.Groups["value"].Value)
.ToArray();
If you want to read/write the data from/to the file(s):
File.WriteAllLines(#"c:\Output.txt", Regex
.Matches(File.ReadAllText(#"c:\Input.txt"), "(?:id=)(?<value>[0-9]+)(?:&)")
.OfType<Match>()
.Select(match => match.Groups["value"].Value));
I think this Code helps you to extract:
const string startString = "id=";
const string endString = "amp";
string test = "ffvreergverfverid=38338ampvevbevvid=3amp";
StringBuilder outfile = new StringBuilder();
do
{
int startPos = test.IndexOf(startString);
int endPos = test.IndexOf(endString);
outfile.AppendLine(test.Substring(startPos, endPos - startPos));
test = test.Remove(startPos, (endPos + endString.Length)- startPos);
}while(test.Contains(startString));
This looks like you are reading URL's
I personally would check out StreamReader class, you are going to need to read each character until you find a series of characters, so something like:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace StrReader
{
class Program
{
static void Main(string[] args)
{
bool hit = false;
string start = "?id=";
string end = "&";
string buffer = string.Empty;
string endBuffer = string.Empty;
using(StreamReader sr = new StreamReader(#"C:\development\zaza.txt"))
{
while (sr.Peek() >= 0)
{
string value = ((char)sr.Read()).ToString();
if(!hit){
if (start.IndexOf(value) > -1)
buffer = string.Concat(buffer, value);
else buffer = string.Empty;
hit = string.Equals(buffer, start, StringComparison.CurrentCultureIgnoreCase);
if (buffer.Length >= start.Length && hit)
buffer = string.Empty;
}
else
{
if (end.IndexOf(value) > -1)
endBuffer = String.Concat(endBuffer, value);
else
endBuffer = string.Empty;
buffer = string.Concat(buffer, value);
if (endBuffer == end)
{
Console.WriteLine(buffer.Substring(0,buffer.Length - endBuffer.Length ));
buffer = string.Empty;
hit = false;
}
buffer = string.Concat(buffer, value);
}
}
}
Console.ReadLine();
}
}
}
The reason you want to read each character is if you read the entire file into memory you are going to be sad, this will slow your machine down quite badly.
Just some comments on the code above change c:\development\zaza.txt to the big file, also you will need to change the start identifier ?id= to something you need. Finally the end identifier (&) needs to be altered to your requirements.
When I connect to pop3.live.com the connection is fine and it also shows me the amount of messages I have and the size of the file but when I try and use "RETR" to get the messages and show them on a console application nothing is presented.
Here is what I have so far
string str = string.Empty;
string strTemp = string.Empty;
using (TcpClient tc = new TcpClient())
{
tc.Connect("pop3.live.com", 995);
using (SslStream sl = new SslStream(tc.GetStream()))
{
sl.AuthenticateAsClient("pop3.live.com");
using (StreamReader sr = new StreamReader(sl))
{
using (StreamWriter sw = new StreamWriter(sl))
{
sw.WriteLine("USER " + _username);
sw.Flush();
sw.WriteLine("PASS "+ _password);
sw.Flush();
sw.WriteLine("LIST");
sw.Flush();
sw.WriteLine("RETR");
sw.Flush();
sw.WriteLine("QUIT ");
sw.Flush();
while ((strTemp = sr.ReadLine()) != null)
{
if (strTemp == "." || strTemp.IndexOf("-ERR") != -1)
{
break;
}
str += strTemp;
}
}
}
}
}
Console.WriteLine(str);
Console.ReadLine();
First you have to use the LIST command, which lists the message numbers. Then issue one or more RETR commands with a single message number from the previous list. Message numbers does not necessarily start from 1! See also my comment on your question about debugging this issue.
For example:
LIST
+OK 2 messages (4095)
1 710
2 3385
.
RETR 1
+OK 710 octets
Return-Path: <john#example.com>
...
With RETR, you need to specify which message to retrieve. RETR without a number is not supported per the POP3 specification.