www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Reading file as binary

reply "baws" <blaquee gmail.com> writes:
Im trying to learn D, lovely language for a C++ lover. I have a 
file Im trying to parse, but I need to read the contents as 
binary data. I also need help understanding how read() works. I'd 
like to read the first four bytes which identify the file header, 
I need it to show as a sequence of bytes, how can i output the 
first 4 bytes to show like 0xFFCF?

With my code, im getting the integer values, If i use 
cast(byte[]) on read and writefln("Reading header info: 0x%x", 
bytesRead[0]);

Ill only get the first byte 0xCF.


import std.stdio;
import std.file;
import std.array;

struct xsdhead{
     int head1;
     int head2;
     int numTables;
};

immutable int headerInfo1 = 0xFFCF;
immutable int headerInfo2 = 0x0002;

int main(string [] args){
     writeln("start");
     if(args[1] == null){
         writeln("pass a file");
         return 0;
     }
     auto file = args[1];
     writeln("Working on ", file);

     auto bytesRead =  cast(byte[]) read(file, 4);
     writefln("Reading header info: %s", bytesRead);
     writefln("Address of caret is: 0x%X", &bytesRead);

     return 0;
}
May 29 2013
next sibling parent "baws" <blaquee gmail.com> writes:
On Wednesday, 29 May 2013 at 22:03:24 UTC, baws wrote:
 Im trying to learn D, lovely language for a C++ lover. I have a 
 file Im trying to parse, but I need to read the contents as 
 binary data. I also need help understanding how read() works. 
 I'd like to read the first four bytes which identify the file 
 header, I need it to show as a sequence of bytes, how can i 
 output the first 4 bytes to show like 0xFFCF?

 With my code, im getting the integer values, If i use 
 cast(byte[]) on read and writefln("Reading header info: 0x%x", 
 bytesRead[0]);

 Ill only get the first byte 0xCF.


 import std.stdio;
 import std.file;
 import std.array;

 struct xsdhead{
     int head1;
     int head2;
     int numTables;
 };

 immutable int headerInfo1 = 0xFFCF;
 immutable int headerInfo2 = 0x0002;

 int main(string [] args){
     writeln("start");
     if(args[1] == null){
         writeln("pass a file");
         return 0;
     }
     auto file = args[1];
     writeln("Working on ", file);

     auto bytesRead =  cast(byte[]) read(file, 4);
     writefln("Reading header info: %s", bytesRead);
     writefln("Address of caret is: 0x%X", &bytesRead);

     return 0;
 }
Oh clap guys, sorry for wasting time, I just noticed the std.stdio.File library! Ill come back to this later!
May 29 2013
prev sibling next sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Wednesday, 29 May 2013 at 22:03:24 UTC, baws wrote:
 With my code, im getting the integer values, If i use 
 cast(byte[]) on read and writefln("Reading header info: 0x%x", 
 bytesRead[0]);
You're reading the file correctly, just not printing it all out in hex.
     writefln("Reading header info: %s", bytesRead);
this line should be printing the right data, just in decimal notation instead of hex. If you do the %x with one byte at a time you'll probably get the output you want: byte[] a = [10, 16, 32, 123]; writef("0x"); foreach(b; a) writef("%x", b); writef("\n");
May 29 2013
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 05/29/2013 03:23 PM, Adam D. Ruppe wrote:

          byte[] a = [10, 16, 32, 123];
          writef("0x");
          foreach(b; a)
              writef("%x", b);
          writef("\n");
There is also the nested array formatting. Pretty cool but dyslecix! :) writefln("0x%(%x%)", a); Ali
May 29 2013
parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Ali Çehreli:

     writefln("0x%(%x%)", a);
But usually I prefer to show all the zero nibbles: void main() { import std.stdio; ubyte[] a = [10, 16, 32, 123]; writefln("0x%(%02x%)", a); // Output: 0xa10207b static assert(is(typeof(a[0]) == ubyte), "Only ubyte[]"); writefln("0x%(%x%)", a); // Output: 0x0a10207b } Bye, bearophile
May 29 2013
next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
 void main() {
     import std.stdio;
     ubyte[] a = [10, 16, 32, 123];
     writefln("0x%(%02x%)", a); // Output: 0xa10207b
     static assert(is(typeof(a[0]) == ubyte), "Only ubyte[]");
     writefln("0x%(%x%)", a);   // Output: 0x0a10207b
 }
I have pasted the outputs inverted, sorry. Bye, bearophile
May 29 2013
prev sibling parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 05/29/2013 04:11 PM, bearophile wrote:

 Ali Çehreli:

     writefln("0x%(%x%)", a);
But usually I prefer to show all the zero nibbles:
      writefln("0x%(%02x%)", a); // Output: 0xa10207b
And only then the output would make sense. Thanks. :) Ali
May 29 2013
prev sibling parent reply "baws" <blaquee gmail.com> writes:
On Wednesday, 29 May 2013 at 22:03:24 UTC, baws wrote:
 Im trying to learn D, lovely language for a C++ lover. I have a 
 file Im trying to parse, but I need to read the contents as 
 binary data. I also need help understanding how read() works. 
 I'd like to read the first four bytes which identify the file 
 header, I need it to show as a sequence of bytes, how can i 
 output the first 4 bytes to show like 0xFFCF?

 With my code, im getting the integer values, If i use 
 cast(byte[]) on read and writefln("Reading header info: 0x%x", 
 bytesRead[0]);

 Ill only get the first byte 0xCF.


 import std.stdio;
 import std.file;
 import std.array;

 struct xsdhead{
     int head1;
     int head2;
     int numTables;
 };

 immutable int headerInfo1 = 0xFFCF;
 immutable int headerInfo2 = 0x0002;

 int main(string [] args){
     writeln("start");
     if(args[1] == null){
         writeln("pass a file");
         return 0;
     }
     auto file = args[1];
     writeln("Working on ", file);

     auto bytesRead =  cast(byte[]) read(file, 4);
     writefln("Reading header info: %s", bytesRead);
     writefln("Address of caret is: 0x%X", &bytesRead);

     return 0;
 }
Erhm, why isnt this compiling guys? all i did was add your suggestions... :/ import std.stdio; import std.file; import std.array; struct xsdhead{ int head1; int head2; int numTables; }; immutable int headerInfo1 = 0xFFCF; immutable int headerInfo2 = 0x0002; int main(string [] args){ writeln("start"); if(!args[1]){ writeln("pass a file"); return 0; } auto file = args[1]; writeln("Working on: ", file); auto bytesRead = cast(byte[])read(file, 4); writefln("Reading header info: 0x%(%02x%)", bytesRead); return 0; }
May 29 2013
parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 05/29/2013 09:00 PM, baws wrote:

 Erhm, why isnt this compiling guys? all i did was add your
 suggestions... :/
Your code compiles here with dmd 2.062 and v2.063-devel-f6d55a9-dirty. What is the compiler error in your case? The program has a run time error though: args[1] is an invalid access when args has only one element. Also, you are making an incorrect assumption: Unlike C, the last element of args is not null; such an element simply does not exist. You need a check like this: if (args.length != 2) { // ... } Ali
May 29 2013