I'd like to compress a string using SevenZipSharp and have cobbled together a C# console application (I'm new to C#) using the following code, (bits and pieces of which came from similar questions here on SO).
The compress part seems to work (albeit I'm passing in a file instead of a string), output of the compressed string to the console looks like gibberish but I'm stuck on the decompress...
I'm trying to do the same thing as here (I think):
https://stackoverflow.com/a/4305399/3451115
https://stackoverflow.com/a/45861659/3451115
https://stackoverflow.com/a/36331690/3451115
Appreciate any help, ideally the console will display the compressed string followed by the decompressed string.
Thanks :)
using System;
using System.IO;
using SevenZip;
namespace _7ZipWrapper
{
public class Program
{
public static void Main()
{
SevenZipCompressor.SetLibraryPath(#"C:\Temp\7za64.dll");
SevenZipCompressor compressor = new SevenZipCompressor();
compressor.CompressionMethod = CompressionMethod.Ppmd;
compressor.CompressionLevel = SevenZip.CompressionLevel.Ultra;
compressor.ScanOnlyWritable = true;
var compStream = new MemoryStream();
var decompStream = new MemoryStream();
compressor.CompressFiles(compStream, #"C:\Temp\a.txt");
StreamReader readerC = new StreamReader(compStream);
Console.WriteLine(readerC.ReadToEnd());
Console.ReadKey();
// works up to here... below here output to consol is: ""
SevenZipExtractor extractor = new SevenZip.SevenZipExtractor(compStream);
extractor.ExtractFile(0, decompStream);
StreamReader readerD = new StreamReader(decompStream);
Console.WriteLine(readerD.ReadToEnd());
Console.ReadKey();
}
}
}
The result of compression is binary data - it isn't a string. If you try to read it as a string, you'll just see garbage. That's to be expected - you shouldn't be treating it as a string.
The next problem is that you're trying to read from compStream twice, without "rewinding" it first. You're starting from the end of the stream, which means there's no data for it to decompress. If you just add:
compStream.Position = 0;
before you create the extractor, you may well find it works immediately. You may also need to rewind the decompStream before reading from it. So you'd have code like this:
// Rewind to the start of the stream before decompressing
compStream.Position = 0;
SevenZipExtractor extractor = new SevenZip.SevenZipExtractor(compStream);
extractor.ExtractFile(0, decompStream);
// Rewind to the start of the decompressed stream before reading
decompStream.Position = 0;
Related
as you can imagine I'm adressing my question to you as I wasn't able to solve my problem doing research. Also I'm rather unexperienced so maybe you can help.
At work I have a simulation program that produces huge amount of data so I want to write out every time increment as VTK file using binary. For reasons of acquiring the data I want to implement this vtkWrite by myself.
Therefore as you might know, I need to write some lines in ASCII-format that contain the declaration of the data part that I need to write in binary format.
Up to now my code looks like this:
public void WriteVTKBin(int increment, string output_dir, bool format)
{
int data_structure = 12;
int[,] ElementTypes = new int[hex8Elements.numberOfElements, 1];
for (int ii = 0; ii < ElementTypes.Length; ii++) ElementTypes[ii, 0] = data_structure;
string File_name = "output_bin_" + increment + ".vtk";
var output = new FileStream(#output_dir + "/" + File_name, FileMode.Create);
var output_Stream = new StreamWriter(output);
using (output)
{
output_Stream.WriteLine("# vtk DataFile Version 3.0");
output_Stream.WriteLine("vtk-Output for increment");
if (format) output_Stream.WriteLine("BINARY");
else output_Stream.WriteLine("ASCII");
output_Stream.WriteLine("DATASET UNSTRUCTURED_GRID");
output_Stream.WriteLine("POINTS " + nodes.numberOfNodes + " double");
}
var output_rest = new FileStream(#output_dir + "/" + File_name, FileMode.Append);
var BinWriter = new BinaryWriter(output_rest);
using (output_rest)
{
BinWriter.Write(GetBytesDouble(GetPointsOutput()));
}
}
}
The argument taken from the BinaryWriter is a ByteArray that I produce using a different method.
My idea was to initialize the file with FileMode.Create to overwrite potentially existing old files and then write the header section. Afterwards closing the file, open it again using FileMode.Append and writing my binary data. This I want to repeat until all fields I want to write out are contained in the vtk-file.
The Problem is: The BinaryWriter overwrites my header even though it's in Append-Mode and when I want to close it and write another ASCII-line it tells me that it cannot access an already closed file.
So is there a solution for my approach or is there even a way more sophisticated way to deal with such types of output?
Thank you very much in advance,
RR
You can simply transform your ascii strings to binary and write them to file as such:
ByteArray = Encoding.XXX.GetBytes(text)
Where XXX is the encoding you want
BinaryWriter.Write(ByteArray)
When you open the file it will try to decode it with ascii and your ascii strings will be there for you to read
You have missed using for StreamWriter and BinaryWriter. Change your code like this and it will work:
using (var fstream = new FileStream(..., FileMode.Create))
using (var writer = new StreamWriter(fstream))
{
// Write headers
}
using (var fstream = new FileStream(..., FileMode.Append)
using (var writer = new BinaryWriter(fstream))
{
// Write binary data
}
Also you can encode your headers to byte[] and use only BinaryWriter.
using (var fstream = new FileStream(..., FileMode.Create)
using (var writer = new BinaryWriter(fstream))
{
// Write headers
writer.Write(Encoding.ASCII.GetBytes("..."));
// Write binary data
}
Or just use BinaryWriter to write string.
using (var fstream = new FileStream(..., FileMode.Create)
using (var writer = new BinaryWriter(fstream))
{
// Write headers
writer.Write("...");
// Write binary data
}
I am currently developing a Windows Phone 8 application in which one I have to download a CSV file from a web-service and convert data to a C# business object (I do not use a library for this part).
Download the file and convert data to a C# business object is not an issue using RestSharp.Portable, StreamReader class and MemoryStream class.
The issue I face to is about the bad encoding of the string fields.
With the library RestSharp.Portable, I retrieve the csv file content as a byte array and then convert data to string with the following code (where response is a byte array) :
using (var streamReader = new StreamReader(new MemoryStream(response)))
{
while (streamReader.Peek() >= 0)
{
var csvLine = streamReader.ReadLine();
}
}
but instead of "Jérome", my csvLine variable contains J�rome. I tried several things to obtain Jérome but without success like :
using (var streamReader = new StreamReader(new MemoryStream(response), true))
or
using (var streamReader = new StreamReader(new MemoryStream(response), Encoding.UTF8))
When I open the CSV file with a simple notepad software like notepad++ I obtain Jérome only when the file is encoding in ANSI. But if I try the following code in C# :
using (var streamReader = new StreamReader(new MemoryStream(response), Encoding.GetEncoding("ANSI")))
I have the following exception :
'ANSI' is not a supported encoding name.
Can someone help me to decode correctly my CSV file ?
Thank you in advance for your help or advices !
You need to pick one of these.
https://msdn.microsoft.com/en-us/library/windows/desktop/dd317756(v=vs.85).aspx
If you don't know, you can try to guess it. Guessing isn't a perfect solution, per the answer here.
You can't detect the codepage, you need to be told it. You can analyse the bytes and guess it, but that can give some bizarre (sometimes amusing) results.
From the link of Lawtonfogle I tried to use
using (var streamReader = new StreamReader(new MemoryStream(response), Encoding.GetEncoding("Windows-1252")))
But I had the following error :
'Windows-1252' is not a supported encoding name.
Searching why on the internet, I finally found following thread with the following answer that works for me.
So here the working solution in my case :
using (var streamReader = new StreamReader(new MemoryStream(response), Encoding.GetEncoding("ISO-8859-1")))
{
while (streamReader.Peek() >= 0)
{
var csvLine = streamReader.ReadLine();
}
}
I have the following code:
file.InputStream.Seek(0,0);
Stream s = file.InputStream
s.Position = 0;
s = File.Create(path);
My goal is for the final output to be a duplicate of the original file. Using file.SaveAs(path) successfully does this. However converting it to a stream and then trying to create the file does not. Is there something completely obvious that I'm missing or is there a bigger problem?
The problem is this line:
s = File.Create(path)
That doesn't do what you want it to. That's creating a new stream - at which point you're ignoring the old one entirely.
You probably want something like:
using (var output = File.Create(path))
{
file.InputStream.CopyTo(output);
}
Hi there iam trying to convert text to speech (wav) in the memorystream convert it to mp3 and then play it on the users page.so need i help what to do next?
here is my asmx code :
[WebMethod]
public byte[] StartSpeak(string Word)
{
MemoryStream ms = new MemoryStream();
using (System.Speech.Synthesis.SpeechSynthesizer synhesizer = new System.Speech.Synthesis.SpeechSynthesizer())
{
synhesizer.SelectVoiceByHints(System.Speech.Synthesis.VoiceGender.NotSet, System.Speech.Synthesis.VoiceAge.NotSet, 0, new System.Globalization.CultureInfo("en-US"));
synhesizer.SetOutputToWaveStream(ms);
synhesizer.Speak(Word);
}
return ms.ToArray();
}
Thanks.
Just wanted to post my example too using NAudio.Lame:
NuGet:
Install-Package NAudio.Lame
Code Snip: Mine obviously returns a byte[] - I have a separate save to disk method b/c I think it makes unit testing easier.
public static byte[] ConvertWavToMp3(byte[] wavFile)
{
using(var retMs = new MemoryStream())
using (var ms = new MemoryStream(wavFile))
using(var rdr = new WaveFileReader(ms))
using (var wtr = new LameMP3FileWriter(retMs, rdr.WaveFormat, 128))
{
rdr.CopyTo(wtr);
return retMs.ToArray();
}
}
You need an MP3 compressor library. I use Lame via the Yeti Lame wrapper. You can find code and a sample project here.
Steps to get this working:
Copy the following files from MP3Compressor to your project:
AudioWriters.cs
Lame.cs
Lame_enc.dll
Mp3Writer.cs
Mp3WriterConfig.cs
WaveNative.cs
WriterConfig.cs
In the project properties for Lame_enc.dll set the Copy to Output property to Copy if newer or Copy always.
Edit Lame.cs and replace all instances of:
[DllImport("Lame_enc.dll")]
with:
[DllImport("Lame_enc.dll", CallingConvention = CallingConvention.Cdecl)]
Add the following code to your project:
public static Byte[] WavToMP3(byte[] wavFile)
{
using (MemoryStream source = new MemoryStream(wavFile))
using (NAudio.Wave.WaveFileReader rdr = new NAudio.Wave.WaveFileReader(source))
{
WaveLib.WaveFormat fmt = new WaveLib.WaveFormat(rdr.WaveFormat.SampleRate, rdr.WaveFormat.BitsPerSample, rdr.WaveFormat.Channels);
// convert to MP3 at 96kbit/sec...
Yeti.Lame.BE_CONFIG conf = new Yeti.Lame.BE_CONFIG(fmt, 96);
// Allocate a 1-second buffer
int blen = rdr.WaveFormat.AverageBytesPerSecond;
byte[] buffer = new byte[blen];
// Do conversion
using (MemoryStream output = new MemoryStream())
{
Yeti.MMedia.Mp3.Mp3Writer mp3 = new Yeti.MMedia.Mp3.Mp3Writer(output, fmt, conf);
int readCount;
while ((readCount = rdr.Read(buffer, 0, blen)) > 0)
mp3.Write(buffer, 0, readCount);
mp3.Close();
return output.ToArray();
}
}
}
Either add a reference to System.Windows.Forms to your project (if it's not there already), or edit AudioWriter.cs and WriterConfig.cs to remove the references. Both of these have a using System.Windows.Forms; that you can remove, and WriterConfig.cs has a ConfigControl declaration that needs to be removed/commented out.
Once all of that is done you should have a functional in-memory wave-file to MP3 converter that you can use to convert the WAV file that you are getting from the SpeechSynthesizer into an MP3.
This is a bit old now, but since you haven't accepted the answer I previously provided...
I have recently built an extension for NAudio that encapsulates the LAME library to provide simplified MP3 encoding.
Use the NuGet package manager to find NAudio.Lame. Basic example for using it available here.
Assuming you're trying to convert the output into MP3, you need something that can handle transcoding the audio. There are a number of tools available, but my personal preference is FFmpeg. It's a command line tool so you will need to take that into account, but otherwise it's very easy to use.
There's lots of information online, but you can start by checking out their documentation here.
I had a similar requirement in .net4.0 to convert 8bit 8Khz mono wav and used the following code
public void WavToMp3(string wavPath, string fileId)
{
var tempMp3Path = TempPath + "tempFiles\\" + fileId + ".mp3";
var mp3strm = new FileStream(tempMp3Path, FileMode.Create);
try
{
using (var reader = new WaveFileReader(wavPath))
{
var blen = 65536;
var buffer = new byte[blen];
int rc;
var bit16WaveFormat = new WaveFormat(16000, 16, 1);
using (var conversionStream = new WaveFormatConversionStream(bit16WaveFormat, reader))
{
var targetMp3Format = new WaveLib.WaveFormat(16000, 16, 1);
using (var mp3Wri = new Mp3Writer(mp3strm, new Mp3WriterConfig(targetMp3Format, new BE_CONFIG(targetMp3Format,64))))
{
while ((rc = conversionStream.Read(buffer, 0, blen)) > 0) mp3Wri.Write(buffer, 0, rc);
mp3strm.Flush();
conversionStream.Close();
}
}
reader.Close();
}
File.Move(tempMp3Path, TempPath + fileId + ".mp3");
}
finally
{
mp3strm.Close();
}
}
Prerequists:
.net 4 compiled yeti library (to obtain it download this older one (http://www.codeproject.com/KB/audio-video/MP3Compressor/MP3Compressor.zip) and convert it to .net4.0 then build the solution to obtain the new version dlls)
download the NAudio libraries (as Lame support 16bit wav sample only i had to first convert it from 8bit to 16bit wav)
I have used a buffer size of 64kpbs (my custom requirement)
have a try:
using (WaveStream waveStream = WaveFormatConversionStream.CreatePcmStream(new
Mp3FileReader(inputStream)))
using (WaveFileWriter waveFileWriter = new WaveFileWriter(outputStream, waveStream.WaveFormat))
{
byte[] bytes = new byte[waveStream.Length];
waveStream.Position = 0;
waveStream.Read(bytes, 0, waveStream.Length);
waveFileWriter.WriteData(bytes, 0, bytes.Length);
waveFileWriter.Flush();
}
I'm trying to convert a .db file to binary so I can stream it across a web server. I'm pretty new to C#. I've gotten as far as looking at code snippets online but I'm not really sure if the code below puts me on the right track. How I can write the data once I read it? Does BinaryReader automatically open up and read the entire file so I can then just write it out in binary format?
class Program
{
static void Main(string[] args)
{
using (FileStream fs = new FileStream("output.bin", FileMode.Create))
{
using (BinaryWriter bw = new BinaryWriter(fs))
{
long totalBytes = new System.IO.FileInfo("input.db").Length;
byte[] buffer = null;
BinaryReader binReader = new BinaryReader(File.Open("input.db", FileMode.Open));
}
}
}
}
Edit: Code to stream the database:
[WebGet(UriTemplate = "GetDatabase/{databaseName}")]
public Stream GetDatabase(string databaseName)
{
string fileName = "\\\\computer\\" + databaseName + ".db";
if (File.Exists(fileName))
{
FileStream stream = File.OpenRead(fileName);
if (WebOperationContext.Current != null)
{
WebOperationContext.Current.OutgoingResponse.ContentType = "binary/.bin";
}
return stream;
}
return null;
}
When I call my server, I get nothing back. When I use this same type of method for a content-type of image/.png, it works fine.
All the code you posted will actually do is copy the file input.db to the file output.bin. You could accomplish the same using File.Copy.
BinaryReader will just read in all of the bytes of the file. It is a suitable start to streaming the bytes to an output stream that expects binary data.
Once you have the bytes corresponding to your file, you can write them to the web server's response like this:
using (BinaryReader binReader = new BinaryReader(File.Open("input.db",
FileMode.Open)))
{
byte[] bytes = binReader.ReadBytes(int.MaxValue); // See note below
Response.BinaryWrite(bytes);
Response.Flush();
Response.Close();
Response.End();
}
Note: The code binReader.ReadBytes(int.MaxValue) is for demonstrating the concept only. Don't use it in production code as loading a large file can quickly lead to an OutOfMemoryException. Instead, you should read in the file in chunks, writing to the response stream in chunks.
See this answer for guidance on how to do that
https://stackoverflow.com/a/8613300/141172