Years ago I stared using ReadLineEx because it was necessary. Now I can’t get it working, do I even need it? This is what I was using.
public static string ReadLine(string file, int line)
{
if (Detect.SD_Card() & File.Exists(file))
{
lock (CardLock)
{
using (StreamReader r = new StreamReader(file))
{
SAL.StatusLED[3].Write(true);
int i = 0;
while (ReadLineEx(r) != null & i != line)
{
i++;
}
SAL.StatusLED[3].Write(false);
if (i == line)
{
return ReadLineEx(r);
}
}
}
}
return "EOF";
}
public static string ReadLineEx(StreamReader sr)
{
int newChar = 0;
int bufLen = 512; // NOTE: the smaller buffer size.
char[] readLineBuff = new char[bufLen];
int growSize = 512;
int curPos = 0;
while ((newChar = sr.Read()) != -1)
{
if (curPos == bufLen)
{
if ((bufLen + growSize) > 0xffff)
{
throw new Exception();
}
char[] tempBuf = new char[bufLen + growSize];
Array.Copy(readLineBuff, 0, tempBuf, 0, bufLen);
readLineBuff = tempBuf;
bufLen += growSize;
}
readLineBuff[curPos] = (char)newChar;
if (readLineBuff[curPos] == '\n')
{
return new string(readLineBuff, 0, curPos);
}
if (readLineBuff[curPos] == '\r')
{
sr.Read();
return new string(readLineBuff, 0, curPos);
}
curPos++;
}
if (curPos == 0) return null; // Null fix.
return new string(readLineBuff, 0, curPos);
}
If I don’t need it, can I have an example of using readline properly.
I’m successfully using the code above to loop through the lines in a txt file on an SD_Card. Except when I read about the 10th line. It fails with the following error.
GC: 10msec 1011444 bytes used, 6328224 bytes available
Type 0F (STRING ): 2808 bytes
Type 11 (CLASS ): 11484 bytes
Type 12 (VALUETYPE ): 4932 bytes
Type 13 (SZARRAY ): 8508 bytes
Type 01 (BOOLEAN ): 84 bytes
Type 03 (U1 ): 876 bytes
Type 04 (CHAR ): 516 bytes
Type 07 (I4 ): 720 bytes
Type 0F (STRING ): 1944 bytes
Type 11 (CLASS ): 3540 bytes
Type 12 (VALUETYPE ): 828 bytes
Type 15 (FREEBLOCK ): 6328224 bytes
Type 16 (CACHEDBLOCK ): 240 bytes
Type 17 (ASSEMBLY ): 35448 bytes
Type 18 (WEAKCLASS ): 48 bytes
Type 19 (REFLECTION ): 192 bytes
Type 1B (DELEGATE_HEAD ): 540 bytes
Type 1D (OBJECT_TO_EVENT ): 216 bytes
Type 1E (BINARY_BLOB_HEAD ): 935664 bytes
Type 1F (THREAD ): 1920 bytes
Type 20 (SUBTHREAD ): 240 bytes
Type 21 (STACK_FRAME ): 3048 bytes
Type 22 (TIMER_HEAD ): 72 bytes
Type 23 (LOCK_HEAD ): 120 bytes
Type 24 (LOCK_OWNER_HEAD ): 48 bytes
Type 27 (FINALIZER_HEAD ): 384 bytes
Type 31 (IO_PORT ): 288 bytes
Type 34 (APPDOMAIN_HEAD ): 72 bytes
Type 36 (APPDOMAIN_ASSEMBLY ): 5172 bytes
#### Exception System.IO.IOException - CLR_E_FILE_IO (5) ####
#### Message:
#### Microsoft.SPOT.IO.NativeFileStream::GetLength [IP: 0000] ####
#### System.IO.FileStream::get_Length [IP: 001b] ####
#### Industry_ONE.Tools.FileManagement.FileManager::ReadLineEx [IP: 00ac] ####
#### Industry_ONE.Tools.FileManagement.FileManager::ReadLine [IP: 003b] ####
#### Industry_ONE.Tools.FileManagement.Log::ReadLine [IP: 0050] ####
#### DEMO.Tools.Diag::ReadLog [IP: 009b] ####
#### DEMO.Tools.Diag::MENU_Actions [IP: 0153] ####
#### DEMO.Program::menu_return [IP: 006c] ####
#### DEMO.MENU::RunThisOption [IP: 0005] ####
#### DEMO.MENU::selectMenu [IP: 0067] ####
#### DEMO.MENU::doMenuStuff [IP: 0130] ####
#### DEMO.MENU::on_keyTimerTick [IP: 0004] ####
A first chance exception of type 'System.IO.IOException' occurred in Microsoft.SPOT.IO.dll
that exception happening just after a GC leads me to believe your file stream went out of scope and was GCed, then your next read dies… I’d be checking code outside that section you showed above.
I cut out as much crap as possible and ended up with the below solution. I can read line by line until about line 100. GC runs and kills the line read.
using System;
using Microsoft.SPOT;
using System.IO;
using Microsoft.SPOT.Hardware;
using Microsoft.SPOT.IO;
using System.Threading;
using GHI.IO.Storage;
namespace test
{
public class Program
{
private static Object LogLock = new Object();
private static Object CardLock = new Object();
public static string FullLogFile = @ "\SD\Logs\FullLog.txt";
public static string ErrorLogFile = @ "\SD\Logs\ErrorLog.txt";
private static string FullLog = "";
private static string ErrorLog = "";
public static InputPort CD = new InputPort(GHI.Pins.G120.P2_21, false, Port.ResistorMode.PullUp); //This will depend on your board.
public static void Main()
{
int x = 0;
while (true)
{
Debug.Print(ReadLine(x, 0));
Debug.Print(x.ToString());
Thread.Sleep(100);
x++;
}
}
public static string ReadLine(int line, int Level = 0)
{
lock (LogLock)
{
string name = FullLogFile;
string memorylog = FullLog;
if (Level == 1)
{
name = ErrorLogFile;
memorylog = ErrorLog;
}
if (Detect_SD_Card())
{
if (File.Exists(name))
{
try
{
string s = FileManager_ReadLine(name, line);
return s;
}
catch
{
return " End of Log";
}
}
else
{
return " End of Log";
}
}
else
{
try
{
string[] StringLine = (memorylog.Split('\n'));
if (line >= StringLine.Length)
{
return " End of Log";
}
else
{
return StringLine[line];
}
}
catch
{
}
}
return " End of Log";
}
}
public static string FileManager_ReadLine(string file, int line)
{
if (Detect_SD_Card() & File.Exists(file))
{
lock (CardLock)
{
using (StreamReader r = new StreamReader(file))
{
//SAL.StatusLED[3].Write(true);
int i = 0;
while (FileManager_ReadLineEx(r) != null & i != line)
{
i++;
}
//SAL.StatusLED[3].Write(false);
if (i == line)
{
return FileManager_ReadLineEx(r);
}
}
}
}
return "EOF";
}
public static string FileManager_ReadLineEx(StreamReader sr)
{
int newChar = 0;
int bufLen = 512; // NOTE: the smaller buffer size.
char[] readLineBuff = new char[bufLen];
int growSize = 512;
int curPos = 0;
while ((newChar = sr.Read()) != -1)
{
if (curPos == bufLen)
{
if ((bufLen + growSize) > 0xffff)
{
throw new Exception();
}
char[] tempBuf = new char[bufLen + growSize];
Array.Copy(readLineBuff, 0, tempBuf, 0, bufLen);
readLineBuff = tempBuf;
bufLen += growSize;
}
readLineBuff[curPos] = (char)newChar;
if (readLineBuff[curPos] == '\n')
{
return new string(readLineBuff, 0, curPos);
}
if (readLineBuff[curPos] == '\r')
{
sr.Read();
return new string(readLineBuff, 0, curPos);
}
curPos++;
}
if (curPos == 0) return null; // Null fix.
return new string(readLineBuff, 0, curPos);
}
public static bool Detect_SD_Card()
{
//If mounted, return true;
//Else try the CD[Chip detect] port to see if a card is inserted;
//If failing to initilise input port or CD is empty, return false;
//If not mounted, but card is seen as inserted, Try mouting;
//If mounting works then return true. Else,return false;
//If card won't mount -format
if (CD.Read())
{
Debug.Print("Card not inserted.");
return false;
}
try
{
if (VolumeInfo.GetVolumes()[0].IsFormatted)
{
string rootDirectory = VolumeInfo.GetVolumes()[0].RootDirectory;
return true;
}
}
catch
{
Debug.Print("nothing mounted yet?");
}
try
{
// Card might be inserted. Lets try mounting.
SDCard SD = new SDCard();
// Mount the file system
SD.Mount();
if (VolumeInfo.GetVolumes()[0].IsFormatted)
{
Debug.Print("SD Card Mounted!");
return true;
}
}
catch
{
Debug.Print("CD pin indicates a card is present, Can't Mount");
}
try
{
//FileManager.Format();
//Debug.Print("Card Formatted");
return true;
}
catch
{
Debug.Print("Can't format the card");
return false;
}
}
}
}