Файл С# для чтения/записи файлов не работает
Мой вопрос основан на наследовании большого количества устаревшего кода, о котором я не могу много о нем говорить. В принципе, у меня есть устройство, которое будет генерировать блок данных. Библиотека, которая вызовет устройство для создания этого блока данных, по какой-то причине я не совсем понимаю и не могу изменить, даже если захочу, записывает этот блок данных на диск.
Эта запись не мгновенная, но может занять до 90 секунд. В это время пользователь хочет получить частичный вид данных, которые создаются, поэтому я хочу иметь потребительский поток, который считывает данные, которые другая библиотека записывает на диск.
Прежде чем я коснусь этого устаревшего кода, я хочу подражать проблеме, используя код, который я полностью контролирую. Я использую С#, якобы потому, что он предоставляет большую функциональность, которую я хочу.
В классе производителя у меня есть этот код, создающий случайный блок данных:
FileStream theFS = new FileStream(this.ScannerRawFileName,
FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read);
//note that I need to be able to read this elsewhere...
BinaryWriter theBinaryWriter = new BinaryWriter(theFS);
int y, x;
for (y = 0; y < imheight; y++){
ushort[] theData= new ushort[imwidth];
for(x = 0; x < imwidth;x++){
theData[x] = (ushort)(2*y+4*x);
}
byte[] theNewArray = new byte[imwidth * 2];
Buffer.BlockCopy(theImage, 0, theNewArray, 0, imwidth * 2);
theBinaryWriter.Write(theNewArray);
Thread.Sleep(mScanThreadWait); //sleep for 50 milliseconds
Progress = (float)(y-1 >= 0 ? y-1 : 0) / (float)imheight;
}
theFS.Close();
До сих пор так хорошо. Этот код работает. Текущая версия (с использованием FileStream и BinaryWriter) представляется эквивалентной (хотя и более медленной, из-за копии) с использованием File.Open с теми же параметрами и BinaryFormatter на ushort [] записывается на диск.
Но затем я добавляю потребительский поток:
FileStream theFS;
if (!File.Exists(theFileName)) {
//do error handling
return;
}
else {
theFS = new FileStream(theFileName, FileMode.Open,
FileAccess.Read, FileShare.Read);
//very relaxed file opening
}
BinaryReader theReader = new BinaryReader(theFS);
//gotta do this copying in order to handle byte array swaps
//frustrating, but true.
byte[] theNewArray = theReader.ReadBytes(
(int)(imheight * imwidth * inBase.Progress) * 2);
ushort[] theData = new ushort[((int)(theNewArray.Length/2))];
Buffer.BlockCopy(theNewArray, 0, theData, 0, theNewArray.Length);
Теперь возможно, что объявление NewArray сломано и вызовет какое-то переполнение чтения. Однако этот код так и не дошел, потому что он всегда всегда ломается, пытаясь открыть новый FileStream с помощью System.IO.IOException, в котором говорится, что другой процесс открыл файл.
Я устанавливаю перечисления FileAccess и FileShare, как указано в документации FileStream в MSDN, но кажется, что я просто не могу делать то, что хочу (т.е. писать в одном потоке, читать в другом). Я понимаю, что это приложение немного неортодоксально, но когда я получаю фактическое устройство, мне придется делать то же самое, но с помощью MFC.
В любом случае, что я забываю? Это то, что я хочу сделать возможным, поскольку это указано в документации?
Спасибо!
MMR
Ответы
Ответ 1
Ваш потребитель должен указать FileShare.ReadWrite.
Пытаясь открыть файл как FileShare.Read у потребителя, вы говорите: "Я хочу открыть файл и позволить другим читать его одновременно"... поскольку существует уже писатель, вызывающий вызов, вы должны разрешить одновременную запись с читателем.
Ответ 2
У меня не было времени проверить это, но я думаю, вам может понадобиться вызвать метод Flush для BinaryWriter
FileStream theFS = new FileStream(this.ScannerRawFileName,
FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read);
//note that I need to be able to read this elsewhere...
BinaryWriter theBinaryWriter = new BinaryWriter(theFS);
int y, x;
for (y = 0; y < imheight; y++){
ushort[] theData= new ushort[imwidth];
for(x = 0; x < imwidth;x++){
theData[x] = (ushort)(2*y+4*x);
}
byte[] theNewArray = new byte[imwidth * 2];
Buffer.BlockCopy(theImage, 0, theNewArray, 0, imwidth * 2);
theBinaryWriter.Write(theNewArray);
Thread.Sleep(mScanThreadWait); //sleep for 50 milliseconds
Progress = (float)(y-1 >= 0 ? y-1 : 0) / (float)imheight;
theBinaryWriter.Flush();
}
theFS.Close();
Жаль, что у меня не было времени проверить это. Я столкнулся с проблемой с созданным мной файлом, который был похож на этот (хотя и не точным), и недостающий "Flush" был виновником.
Ответ 3
Я считаю, что Чак прав, но имейте в виду Единственная причина, по которой это работает вообще, заключается в том, что файловая система достаточно умна, чтобы сериализовать чтение/запись; у вас нет блокировки на файловом ресурсе - это не очень хорошо:)