SML Read binary data from std input - sml

How can a I read binary data from stdIn (standard input) in SML? I know it's easy for text input using ...
TextIO.inputAll TextIO.stdIn
... but how can this be done for an input stream of binary data?

Related

Binary mode + formated text operations or text mode + binary data operations - Does it make sense?

In C++, you can specify a mode for a stream in constructor. But in any of the modes you are still allowed to use both text operations (>> int, >> string, getline) and binary data operations (read, write).
Does it make any sense to open file in binary mode and then read it as text, or open file in text mode and then read it as binary?
Can you give me an example, where this could be usefull?
You could open a file for output as binary than use the formatted text write operations.
This makes sense when you don't want any "extra" translations applied (such as line endings). This would allow you to output 0x0A for a '\n' on all systems, instead of having some systems outputting 0x0D 0x0A for a '\n'.

Is there a way to read an input string with "ifstream"

Currently my programme takes a string as an input which I access using argc and argv
then I use
FILE *fp, *input = stdin;
fp = fopen("input.xml","w+b");
while(fgets(mystring,100,input) != NULL)
{
fputs(mystring,fp);
}
fclose(fp);
I did this part only to create a file input.xml which I then supply to
ifstream in("input.xml");
string s((std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>());
to get s as a string(basic string).
Is there a way to feed my input directly to ifstream? (i.e feeding a string to ifstream).
Let me get this straight:
You read a string from standard input
You write it to a file
You then read it from the file
And use the file stream object to create a string
That's crazy talk!
Drop the file streams and just instantiate the string from STDIN directly:
string s(
(std::istreambuf_iterator<char>(std::cin)),
std::istreambuf_iterator<char>()
);
Remember, std::cin is a std::istream, and the IOStreams part of the standard library is designed for this sort of generic access to data.
Be aware, though, that your approach with std::istreambuf_iterator is not the most efficient, which may be a concern if you're reading a lot of data.
If I get it right then you want to read all the text provided through standard input into a string.
An easy way to achieve this could be the use of std::getline, which reads all the bytes up to a specific delimiter into a string. If you may assume that it is text content (which does not contain any \0-character), you could write the following:
std::string s;
std::getline(cin,s,'\0');

how to read binary file data using dlang

I'm trying to read struct data from specific position in a a binary file.
Found out that I can use import std.stdio and its File, however all i seem to find is all about string handling.
I have c-code written data on binary files that compose of several different structs and they all, as far as I understand coding lay in a oneliner. In order to find specific struct I need to, like in old c,
Open file for reading .... (binary read??)
using sizeof and move to startposition of struct data to read
read data (struct.sizeof data) into receivingbuffer and
Close file
Documentation for std.stdio.File # read talks about reading entire or up to size but can't find how to read as below c-code line?
fseek(filehandle, sizeof(firstStructData), SEEK_SET));
read(filehandle, (char *)nextReceivingBuffer, sizeof(nextReceivingBuffer))
Any ideas or hints?
Try File.seek and File.rawRead. They work like their C counterparts, but rawRead determines the read count from the size of the output buffer you hand it.

Boost ASIO streambuf

I am confused about the input sequence and output sequence in boost asio::streambuf classes.
According to the code examples (for sending data) in the documentation it seems that the buffer representing the input sequence is used for writting to socket and the one representing the output sequence is used for reading.
Example -
boost::asio::streambuf b;
std::ostream os(&b);
os << "Hello, World!\n";
// try sending some data in input sequence
size_t n = sock.send(b.data());
b.consume(n); // sent data is removed from input sequence
Now, is there a nomenclature problem?
The nomenclature for boost::asio::streambuf is similar to that of which is defined in the C++ standard, and used across various classes in the standard template library, wherein data is written to an output stream and data is read from an input stream. For example, one could use std::cout.put() to write to the output stream, and std::cin.get() to read from the input stream.
When manually controlling the streambuf input and output sequences, the general lifecycle of data is as follows:
Buffers get allocated with prepare() for the output sequence.
After data has been written into the output sequence's buffers, the data will be commit()ed. This committed data is removed from the output sequence and appended to the input sequence from which it can be read.
Data is read from the input sequence's buffers obtained via data().
Once data has been read, it can then be removed from the input sequence by consume().
When using Boost.Asio operations that operate on streambuf or stream objects that use a streambuf, such as std::ostream, the underlying input and output sequences will be properly managed. If a buffer is provided to an operation instead, such as passing passing prepare() to a read operation or data() to a write operation, then one must explicitly handle the commit() and consume().
Here is an annotated version of the example code which writes directly from an streambuf to a socket:
// The input and output sequence are empty.
boost::asio::streambuf b;
std::ostream os(&b);
// prepare() and write to the output sequence, then commit the written
// data to the input sequence. The output sequence is empty and
// input sequence contains "Hello, World!\n".
os << "Hello, World!\n";
// Read from the input sequence, writing to the socket. The input and
// output sequences remain unchanged.
size_t n = sock.send(b.data());
// Remove 'n' bytes from the input sequence. If the send operation sent
// the entire buffer, then the input sequence would be empty.
b.consume(n);
And here is the annotated example for reading from a socket directly into an streambuf. The annotations assume that the word "hello" has been received, but not yet read, on the socket:
boost::asio::streambuf b;
// prepare() 512 bytes for the output sequence. The input sequence
// is empty.
auto bufs = b.prepare(512);
// Read from the socket, writing into the output sequence. The
// input sequence is empty and the output sequence contains "hello".
size_t n = sock.receive(bufs);
// Remove 'n' (5) bytes from output sequence appending them to the
// input sequence. The input sequence contains "hello" and the
// output sequence has 507 bytes.
b.commit(n);
// The input and output sequence remain unchanged.
std::istream is(&b);
std::string s;
// Read from the input sequence and consume the read data. The string
// 's' contains "hello". The input sequence is empty, the output
// sequence remains unchanged.
is >> s;
Note how in the above examples, the steam objects handled committed and consuming the streambuf's output and input sequences. However, when the buffers themselves were used (i.e. data() and prepare()), the code needed to explicitly handle commits and consumes.
"Everything is relative"
Albert Einstein
The documentation says:
Characters written to the output sequence of a basic_streambuf object are appended to the input sequence of the same object.
From the point of view of the streambuf it will read from its output sequence and write into its input sequence which might seem kind of inverted, but you can think of the streambuf as a pipe for things to make sense.
From the user (anything that uses the streambuf, including sockets) point of view now, you will write into the ouput sequence of the streambuf and read from its input sequence which seems more natural.
So yeah the same way left and right are inverted depending on what you're facing, inputs and outputs are inverted depending from which side you look at it.
"Don't believe every quote you read on the internet, because I totally didn't say that"
Albert Einstein

How to get boost::iostream to operate in a mode comparable to std::ios::binary?

I have the following question on boost::iostreams. If someone is familiar with writing filters, I would actually appreciate your advices / help.
I am writing a pair of multichar filters, that work with boost::iostream::filtering_stream as data compressor and decompressor.
I started from writing a compressor, picked up some algorithm from lz-family and now am working on a decompressor.
In a couple of words, my compressor splits data into packets, which are encoded separately and then flushed to my file.
When I have to restore data from my file (in programming terms, receive a read(byte_count) request), I have to read a full packed block, bufferize it, unpack it and only then give the requested number of bytes. I've implemented this logic, but right now I'm struggling with the following problem:
When my data is packed, any symbols can appear in the output file. And I have troubles when reading file, which contains symbol (hex 1A, char 26) using boost::iostreams::read(...., size).
If I was using std::ifstream, for example, I would have set a std::ios::binary mode and then this symbol could be read simply.
Any way to achieve the same when implementing a boost::iostream filter which uses boost::iostream::read routine to read char sequence?
Some code here:
// Compression
// -----------
filtering_ostream out;
out.push(my_compressor());
out.push(file_sink("file.out"));
// Compress the 'file.in' to 'file.out'
std::ifstream stream("file.in");
out << stream.rdbuf();
// Decompression
// -------------
filtering_istream in;
in.push(my_decompressor());
in.push(file_source("file.out"));
std::string res;
while (in) {
std::string t;
// My decompressor wants to retrieve the full block from input (say, 4096 bytes)
// but instead retrieves 150 bytes because meets '1A' char in the char sequence
// That obviously happens because file should be read as a binary one, but
// how do I state that?
std::getline(in, t); // <--------- The error happens here
res += t;
}
Short answer for reading file as binary :
specify ios_base::binary when opening file stream.
MSDN Link