FileStream throws File not found - c#

The program is meant to set the file path and the idea is that when the data is set, it should use this function:
public void SendFile(String fileName, long fileSize, NetworkStream io)
{
SendFileNameToServer();
SendFileSizeToServer();
byte[] fileData;
try
{
if (!File.Exists(fileName))
{
throw new FileNotFoundException("File does not exist!");
}
FileStream openFileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read);
BinaryReader bReader = new BinaryReader(openFileStream);
Int32 remainingSize = Convert.ToInt32(_fileSize);
do
{
fileData = bReader.ReadBytes(BUFSIZE);
io.Write(fileData, 0, BUFSIZE);
remainingSize -= BUFSIZE;
} while (remainingSize > BUFSIZE);
do
{
fileData = bReader.ReadBytes(remainingSize);
io.Write(fileData, 0, remainingSize);
remainingSize -= remainingSize;
} while (remainingSize > 0);
bReader.Close();
openFileStream.Flush();
openFileStream.Close();
io.Flush();
io.Close();
}
catch (Exception)
{
throw new Exception();
}
}
to send the file given in the file path to a server-side program which receives the file data.
The problem is that when it gets to the line FileStream openFileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read); it tells me that the file is not found. The exception it gives is Exception:Thrown: "The process cannot access the file 'D:\StepMania\Songs\Fragma\You Are Alive\Green.avi' because it is being used by another process." (System.IO.IOException)
A System.IO.IOException was thrown: "The process cannot access the file 'D:\*FilePath*\Green.avi' because it is being used by another process."
Time: 04-05-2013 21:11:39
Thread:Main Thread[5532] but I can't think of any process that would use this file when StepMania is not running.
I know that the file is there because I check the file path and it's there as it should be. It works just fine if the file is in the exact same folder as the program but other than that, I can't seem to find the solution to this problem. Does anyone have any ideas as to what could be wrong?
If you need any more of my code, please tell me.
Edit:
My server uses this code to receive the file:
public void ReceiveFile(String fileName, NetworkStream io)
{
// TO DO Din egen kode
byte[] fileData = new byte[BUFSIZE];
FileStream writeFileStream = new FileStream(fileName, FileMode.Create);
BinaryWriter bWrite = new BinaryWriter(writeFileStream);
int bytesRead = 0;
long remainingSize = Convert.ToInt32(_fileSize);
do
{
Console.WriteLine("Remaining number of bytes: {0}", remainingSize);
bytesRead = io.Read(fileData, 0, BUFSIZE); // Read max 1000 bytes from server via socket (actual value is placed in "bytesRead"
bWrite.Write(fileData, 0, bytesRead); // write the received bytes into file. the number of received bytes is placed in "bytesRead"
remainingSize -= bytesRead;
}
while (remainingSize > 0);
writeFileStream.Flush();
writeFileStream.Close();
bWrite.Close();
}

Ok, I found the problem: My server-side program interefered with my client-side program. Here's the fixed code for the SendFile code of my client program:
public void SendFile(String fileName, long fileSize, NetworkStream io)
{
SendFileNameToServer();
SendFileSizeToServer();
byte[] fileData;
try
{
FileStream openFileStream = File.OpenRead(fileName);
BinaryReader bReader = new BinaryReader(openFileStream);
Int32 remainingSize = Convert.ToInt32(_fileSize);
do
{
fileData = bReader.ReadBytes(BUFSIZE);
io.Write(fileData, 0, BUFSIZE);
remainingSize -= BUFSIZE;
} while (remainingSize > BUFSIZE);
do
{
fileData = bReader.ReadBytes(remainingSize);
io.Write(fileData, 0, remainingSize);
remainingSize -= remainingSize;
} while (remainingSize > 0);
openFileStream.Flush();
bReader.Close();
openFileStream.Close();
io.Flush();
io.Close();
}
catch (Exception)
{
throw new Exception();
}
}
Here's the ReceiveFile code for my server:
public void ReceiveFile(String fileName, NetworkStream io)
{
// TO DO Din egen kode
byte[] fileData = new byte[BUFSIZE];
FileStream writeFileStream = new FileStream(LIB.extractFileName(fileName), FileMode.Create);
BinaryWriter bWrite = new BinaryWriter(writeFileStream);
int bytesRead = 0;
long remainingSize = Convert.ToInt32(_fileSize);
do
{
Console.WriteLine("Remaining number of bytes: {0}", remainingSize);
bytesRead = io.Read(fileData, 0, BUFSIZE); // Read max 1000 bytes from server via socket (actual value is placed in "bytesRead"
bWrite.Write(fileData, 0, bytesRead); // write the received bytes into file. the number of received bytes is placed in "bytesRead"
remainingSize -= bytesRead;
}
while (remainingSize > 0);
writeFileStream.Flush();
writeFileStream.Close();
bWrite.Close();
}
Again, thank you everyone who answered my post!

Related

Replicate Wave file using Naudio - Copy/Append Latest Available bytes

I have an Active wave recording wave-file.wav happening to the Source folder.
I need to replicate this file to Destination folder with a new name wave-file-copy.wav.
The recording and replication should happen in parallel.
I have implemented a scheduled job, which will run in every 10 minutes and copy the source file to destination.
private static void CopyWaveFile(string destinationFile, string sourceFile){
using (var fs = File.Open(sourceFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)){
using (var reader = new WaveFileReader(fs)){
using (var writer = new WaveFileWriter(destinationFile, reader.WaveFormat)){
reader.Position = 0;
var endPos = (int)reader.Length;
var buffer = new byte[1024];
while (reader.Position < endPos){
var bytesRequired = (int)(endPos - reader.Position);
if (bytesRequired <= 0) continue;
var bytesToRead = Math.Min(bytesRequired, buffer.Length);
var bytesRead = reader.Read(buffer, 0, bytesToRead);
if (bytesRead > 0){
writer.Write(buffer, 0, bytesRead);
}
}
}
}
}
}
The copy operation is working fine, even though the source file is being updated continuously.
Time taken for the copy operation is increasing in linear time, because i am copying the entire file every time.
I am trying to implement a new function ConcatenateWavFiles(), which should update the content of destination file, with the latest available bytes of source recording.
I have tried few sample codes - the approach i am using is :
Read destination file meta info, and get the length.
Set the length of destination file as reader.Position of source file waveReader
Read the source file till end, starting from position.
public static void ConcatenateWavFiles(string destinationFile, string sourceFile){
WaveFileWriter waveFileWriter = null;
var sourceReadOffset = GetWaveFileSize(destinationFile);
try{
using (var fs = File.Open(sourceFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
using (var reader = new WaveFileReader(fs))
{
waveFileWriter = new WaveFileWriter(destinationFile, reader.WaveFormat);
if (!reader.WaveFormat.Equals(waveFileWriter.WaveFormat)){
throw new InvalidOperationException(
"Can't append WAV Files that don't share the same format");
}
var startPos = sourceReadOffset - sourceReadOffset % reader.WaveFormat.BlockAlign;
var endPos = (int) reader.Length;
reader.Position = startPos;
var bytesRequired = (int)(endPos - reader.Position);
var buffer = new byte[bytesRequired];
if (bytesRequired > 0)
{
var bytesToRead = Math.Min(bytesRequired, buffer.Length);
var bytesRead = reader.Read(buffer, 0, bytesToRead);
if (bytesRead > 0)
{
waveFileWriter.Write(buffer, startPos, bytesRead);
}
}
}
}
}
finally{
if (waveFileWriter != null){
waveFileWriter.Dispose();
}
}
}
I was able to get the new content.
Is it possible to append the latest content to existing destination file?
If possible what am I doing wrong in the code?
My code throws the following exception - Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection.
I couldn't find a solution to wave audio file replication with NAudio Library.
But I have implemented a solution using C# MemoryStreams and FileStreams.
Copy the Source file to destination, if destination file doesn't exist.
Append all the latest bytes (recorded after the last operation) to the destination file.
Modify the Wave File Header to to reflect the last appended bytes. (Else the duration of the file will not be updated, only the file size will increase.
Repeat this append operation in regular intervals.
public void ReplicateFile(string destinationFile, string sourceFile){
if (!Directory.Exists(GetRoutePathFromFile(sourceFile)))
return;
if (!File.Exists(sourceFile))
return;
if (Directory.Exists(GetRoutePathFromFile(destinationFile))){
if (File.Exists(destinationFile)){
UpdateLatestWaveFileContent(destinationFile, sourceFile);
}else{
CopyWaveFile(destinationFile, sourceFile);
}
}else{
Directory.CreateDirectory(GetRoutePathFromFile(destinationFile));
CopyWaveFile(destinationFile, sourceFile);
}
}
private static string GetRoutePathFromFile(string file){
var rootPath = Directory.GetParent(file);
return rootPath.FullName;
}
private static void CopyWaveFile(string destination, string source){
var sourceMemoryStream = new MemoryStream();
using (var fs = File.Open(source, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)){
fs.CopyTo(sourceMemoryStream);
}
using (var fs = new FileStream(destination, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.ReadWrite)){
sourceMemoryStream.WriteTo(fs);
}
}
private static void UpdateLatestWaveFileContent(string destinationFile, string sourceFile){
var sourceMemoryStream = new MemoryStream();
long offset = 0;
using (var fs = File.Open(destinationFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)){
offset = fs.Length;
}
using (var fs = File.Open(sourceFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)){
fs.CopyTo(sourceMemoryStream);
}
var length = sourceMemoryStream.Length - offset;
var buffer = sourceMemoryStream.GetBuffer();
using (var fs = new FileStream(destinationFile, FileMode.Append, FileAccess.Write, FileShare.ReadWrite)){
fs.Write(buffer, (int)offset, (int)length);
}
var bytes = new byte[45];
for (var i = 0; i < 45; i++){
bytes[i] = buffer[i];
}
ModifyHeaderDataLength(destinationFile, 0, bytes);
}
private static void ModifyHeaderDataLength(string filename, int position, byte[] data){
using (Stream stream = File.Open(filename, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite))
{
stream.Position = position;
stream.Write(data, 0, data.Length);
}
}
Try Reading the Source File one or two Wav blocks prior to the actual end of the source file.
The case could be that the code is judging the end of the source file too close for comfort.

Copy and update content of actively recording Wav file to a new file

I have an active audio recording happening in WAV format with NAudio Library.
private void RecordStart() {
try {
_sourceStream = new WaveIn {
DeviceNumber = _recordingInstance.InputDeviceIndex,
WaveFormat =
new WaveFormat(
44100,
WaveIn.GetCapabilities(_recordingInstance.InputDeviceIndex).Channels)
};
_sourceStream.DataAvailable += SourceStreamDataAvailable;
if (!Directory.Exists(_recordingInstance.AudioFilePath)) {
Directory.CreateDirectory(_recordingInstance.AudioFilePath);
}
WaveFileWriter _waveWriter = new WaveFileWriter(
_recordingInstance.AudioFilePath + _recordingInstance.AudioFileName,
_sourceStream.WaveFormat);
_sourceStream.StartRecording();
}
catch (Exception exception) {
Log.Error("Recording failes", exception);
}
}
private void SourceStreamDataAvailable(object sender, WaveInEventArgs e) {
if (_waveWriter == null) return;
_waveWriter.Write(e.Buffer, 0, e.BytesRecorded);
_waveWriter.Flush();
}
I want to copy the latest available content to another location. The copied file should be in WAV format, and should be able to play the available duration. Update the destination file, whenever more content is available.
I have Tried the following sample code (using NAudio) with a static WAV file, but the solution is not working.
The resulting WAV file created is corrupted - not in the correct format.
using (WaveFileReader reader = new WaveFileReader(remoteWavFile))
{
byte[] buffer = new byte[reader.Length];
int read = reader.Read(buffer, 0, buffer.Length);
}
When the recording is in progress, the code throws an exception "File is in use by another application".
I have solved the problem with help of NAudio Library itself.
When we only use the WaveFileReader class of NAudio. It will throw the exception - "file is in use by another application".
So I had to create a file stream, which opens the source file - live recording file, with File.Open(inPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite) then pass this stream as an input of WaveFileReader.
Then create a WaveFileWritter class of NAudio, with the same WavFormat of the reader.
copied below is the code, i have used.
public static void CopyWavFile(string inPath, string outPath){
using (var fs = File.Open(inPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)){
using (var reader = new WaveFileReader(fs)){
using (var writer = new WaveFileWriter(outPath, reader.WaveFormat)){
reader.Position = 0;
var endPos = (int)reader.Length;
var buffer = new byte[1024];
while (reader.Position < endPos){
var bytesRequired = (int)(endPos - reader.Position);
if (bytesRequired <= 0) continue;
var bytesToRead = Math.Min(bytesRequired, buffer.Length);
var bytesRead = reader.Read(buffer, 0, bytesToRead);
if (bytesRead > 0){
writer.Write(buffer, 0, bytesRead);
}
}
}
}
}
}

Transfer really large files using WebClient

My requirement is to transfer a zip file of size 400MB or more; The following code works for at least 40MB; But for more I would have to change byte[] bytes = new byte[50000000]; to byte[] bytes = new byte[400000000]; and maxRequestLength to maxRequestLength="409600";
The problem is byte[] bytes = new byte[100000000]; returns an error regarding insufficient space. So how can I transfer large files using WebClient??
WebClient client = new WebClient();
client.AllowWriteStreamBuffering = true;
UriBuilder ub = new UriBuilder("http://localhost:57596/UploadImages.ashx");
ub.Query = "ImageName=" + "DataSet" + DataSetId + ".zip";
client.OpenWriteCompleted += (InputStream, eArguments) =>
{
try
{
using (Stream output = eArguments.Result)
{
output.Write(ImagesAux, 0, (int)ImagesAux.Length);
//numeroimagem++;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
//throw;
}
};
client.OpenWriteAsync(ub.Uri);
in UploadImages.ashx
public void ProcessRequest(HttpContext context)
{
//context.Response.ContentType = "text/plain";
//context.Response.Write("Hello World");
string ImageName = context.Request.QueryString["ImageName"];
string UploadPath = context.Server.MapPath("~/ServerImages/");
using (FileStream stream = File.Create(UploadPath + ImageName))
{
byte[] bytes = new byte[50000000]; //
int bytesToRead = 0;
while ((bytesToRead =
context.Request.InputStream.Read(bytes, 0, bytes.Length)) != 0)
{
stream.Write(bytes, 0, bytesToRead);
stream.Close();
}
}
}
in Web.config
<httpRuntime targetFramework="4.5" maxRequestLength="40960"/>
You should never load everything in memory then write all back to disk, but instead you should load pieces and write them to disk while you are reading them.
When you've done reading you close the stream you are writing to.
Otherwise as soon as you reach sizes as GB you can get an OutOfMemory really quick.
So I would change the writing bytes to disk from this:
using (FileStream stream = File.Create(UploadPath + ImageName))
{
byte[] bytes = new byte[50000000]; //
int bytesToRead = 0;
while ((bytesToRead = context.Request.InputStream.Read(bytes, 0, bytes.Length)) != 0)
{
stream.Write(bytes, 0, bytesToRead);
stream.Close();
}
}
to this:
using (FileStream stream = File.Create(UploadPath + ImageName))
{
byte[] bytes = new byte[1024];
long totalBytes = context.Request.InputStream.Length;
long bytesRead = 0;
int bytesToRead = bytes.Length;
if (totalBytes - bytesRead < bytes.Length)
bytesToRead = (int)(totalBytes - bytesRead);
bytes = new byte[bytesToRead];
while ((bytesToRead = context.Request.InputStream.Read(bytes, bytesRead, bytes.Length)) != 0)
{
stream.Write(bytes, bytesRead, bytes.Length);
bytesRead += bytes.Length;
if (totalBytes - bytesRead < bytes.Length)
bytesToRead = (int)(totalBytes - bytesRead);
bytes = new byte[bytesToRead];
}
stream.Close();
}
1024 would be the buffer size.

Encrypting/Decrypting a file using C# and RSA

I am trying to encrypt and then decrypt an XML file using RSA and C# and while I'm really close, there's a problem. Once it's decrypted, almost all of the file is there but there's a hiccup toward the end. It's either a gap toward the end of the file or more data is appended to the very end of the file.
Here is my encrypt method:
public static bool Encrypt(ProcessingHolder ph)
{
FileInfo inFile = ph.encryptedFI;
FileInfo outFile = ph.unEncryptedFI;
X509Certificate2 daCert = new X509Certificate2(keyFP, daCertPassword);
RSACryptoServiceProvider RSA = (RSACryptoServiceProvider)daCert.PrivateKey;
bool done = false;
FileStream fs = null;
FileStream fso = null;
try
{
//opens the file to encrypt into a filestream object
fs = inFile.OpenRead();
//240 is what the iOS side is using
//algorithm that calculates max bytes ((KeySize - 384) / 8) + 37
//(returns 245)
int chunkSize = 245;
fso = outFile.OpenWrite();
byte[] buffer = new byte[chunkSize];
int totalRead = 0;
while (totalRead < fs.Length)
{
int readBytes = fs.Read(buffer,0, chunkSize);
totalRead += readBytes;
//check to see if the final chunk of data is less than 245 so as not to write empty buffer
if (readBytes < chunkSize) buffer = new byte[readBytes];
//byte[] encr = new byte[readBytes];
//actual encryption
//encr = RSA.Encrypt(buffer, false);
byte[] encr = RSA.Encrypt(buffer, false);
fso.Write(encr, 0, encr.Length);
}
fso.Flush();
fso.Close();
fs.Close();
done = true;
}
catch (Exception ex)
{
Debug.WriteLine("Decrypt failed with message " + ex.Message);
done = false;
}
finally
{
if (fs != null) fs.Close();
if (fso != null) fso.Close();
}
return done;
}
}
and here is my decrypt method:
public static bool Decrypt(ProcessingHolder ph)
{
FileInfo inFile = ph.encryptedFI;
FileInfo outFile = ph.unEncryptedFI;
X509Certificate2 daCert = new X509Certificate2(keyFP, daCertPassword);
RSACryptoServiceProvider RSA = (RSACryptoServiceProvider)daCert.PrivateKey;
bool done = false;
FileStream fs = null;
FileStream fso = null;
try
{
fs = inFile.OpenRead();
int chunkSize = 256;
fso = outFile.OpenWrite();
byte[] buffer = new byte[chunkSize];
int totalRead = 0;
while (totalRead < fs.Length)
{
int readBytes = fs.Read(buffer, 0, chunkSize);
totalRead += readBytes;
//check to see if the final chunk of data is less than 245 so as not to write empty buffer
//if (readBytes < chunkSize) buffer = new byte[readBytes];
byte[] decr = RSA.Decrypt(buffer, false);
fso.Write(decr, 0, decr.Length);
}
fso.Flush();
fso.Close();
fs.Close();
done = true;
}
catch (Exception ex)
{
Debug.WriteLine("Decrypt failed with message " + ex.Message);
done = false;
}
finally
{
if (fs != null) fs.Close();
if (fso != null) fso.Close();
}
return done;
}
banging my head against the wall here, thanks in advance
What happens during encrypting if the file is not a multiple of the length of the chunk size? Ie. a file 500 bytes long would read two sets of 245, but they have 10 bytes left over? This might be loosing the last few bytes at the end or adding extra values?
Maybe you need to add a header to the file with the size in bytes of the decrypted file so that the decrypter knows where to stop and a way to pad out the final block during encryption

overwrite file in Zipping

I try to Zip some .pdf files in C#. My code works fine but when the size of one of the pdfs is big, it is going to overwrite that pdf on the rest of pdfs. I am not sure what is happening. I tried to increase the size of buffer or zip file but still same issue. Do you have any suggestion?
This is my code:
public void ProcessZipRequest(string strQueueID, string strBatchID, string strFtpPath)
{
int intReportCnt = 0;
string strZipFileName = "Order-" + strBatchID + "-" + strQueueID + "-" + DateTime.Now.ToString("MM-dd-yyyy-HH-mm") + ".zip";
strZipFileName = SafeFileName(strZipFileName);
//MemoryStream ms = new MemoryStream();
FileStream ms = new FileStream(#"c:\surf\nikoo.zip", FileMode.Create);
ZipOutputStream oZipStream = new ZipOutputStream(ms); // create zip stream
oZipStream.SetLevel(9); // maximum compression
intReportCnt += 1;
string strRptFilename=string.Empty;
MemoryStream outputStream = new MemoryStream();
if (strQueueID != null)
{
String[] filenames = Directory.GetFiles(#"C:\uploaded");
// setting Report name to path given for Report name
foreach (String filename in filenames)
{
strRptFilename = filename.Substring(filename.LastIndexOf("\\") + 1);
FileStream fs = File.OpenRead(#"C:\uploaded\" + strRptFilename);
int bufferSize = 2048;
int readCount;
byte[] buffer = new byte[bufferSize];
readCount = fs.Read(buffer, 0, bufferSize);
while (readCount>0)
{
outputStream.Write(buffer, 0, readCount);
readCount = fs.Read(buffer, 0, bufferSize);
}
fs.Close();
outputStream.Position = 0;
ZipFile(ref outputStream, strRptFilename, ref oZipStream);
}
}
outputStream.Close();
oZipStream.Finish();
oZipStream.Flush();
oZipStream.IsStreamOwner = false; // False stops the Close also Closing the underlying stream.
oZipStream.Close(); // Must finish the ZipOutputStream before using outputMemStream.
ms.Close();
}
And this is Zipfile Method:
public void ZipFile(ref MemoryStream msFile, string strFilename, ref ZipOutputStream oZipStream)
{
ZipEntry oZipEntry = new ZipEntry(strFilename);
oZipEntry.DateTime = DateTime.Now;
oZipEntry.Size = msFile.Length;
oZipStream.PutNextEntry(oZipEntry);
StreamUtils.Copy(msFile, oZipStream, new byte[4096]);
oZipStream.CloseEntry();
}
I found the issue. I have to create a new MemoyStream in for loop and close it at the end of the loop.
foreach (String filename in filenames)
{
strRptFilename = filename.Substring(filename.LastIndexOf("\\") + 1);
outputStream = new MemoryStream();
FileStream fs = File.OpenRead(#"C:\uploaded\" + strRptFilename);
int bufferSize = 2048;
int readCount;
byte[] buffer = new byte[bufferSize];
readCount = fs.Read(buffer, 0, bufferSize);
while (readCount>0)
{
outputStream.Write(buffer, 0, readCount);
readCount = fs.Read(buffer, 0, bufferSize);
}
fs.Close();
outputStream.Position = 0;
ZipFile(ref outputStream, strRptFilename, ref oZipStream);
fs.Close();
outputStream.Close();
}

Categories

Resources