LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

How do you read hex digits from file?

Can you read hex digits from file using the FiletoArray function? I tried with a test file using '0x10' notation. LW/CVI saw the '0' and '10' as separate numbers.
0 Kudos
Message 1 of 7
(4,291 Views)
You cannot read hexadecimal numbers from a file with the FileToArray function. It was mainly designed to work in conjunction with the ArrayToFile function, to read back what ArrayToFile writes in, which is decimal based numbers only. You should use the FmtFile and ScanFile or fprintf and fscanf functions to write and read hex values from a file. For example:

The ScanFile and FmtFile functions that CVI provides allow you to perform more complex formatting operations with less effort via a more intuitive set of format codes as well, so you might want to look into using those instead.

Jason F.
Applications Engineer
National Instruments
www.ni.com/ask
0 Kudos
Message 2 of 7
(4,291 Views)
OK. Just to take advantage of convenience of FiletoArray we will use decimal integers. But now I'm trying to dynamically allocate a two dimensional array (R x 2) to dump the FiletoArray info, and the function seems to change the array to one-dimensional. Below are snippets of code that do the allocation which seems to work out OK. When FiletoArray is executed, 'reg_array' changes to one-dimensional. Why?

-----------
unsigned short int **reg_array;

alloc_rows = sizeof(unsigned short int *) * words_to_read;
reg_array=(unsigned short int **)malloc(alloc_rows)

alloc_cols = sizeof(unsigned short int) * 2;
for (i=0; i {
reg_array[i]=(unsigned short int *)malloc(alloc_cols)

file_handle = fopen
(pathname, "r");

FileToArray (pathname, reg_array, VAL_UNSIGNED_SHORT_INTEGER, words_to_read*2, words_to_read, VAL_GROUPS_TOGETHER,
VAL_GROUPS_AS_ROWS, VAL_ASCII); /* reg_array changes here */
printf("%u %u\n", reg_array[0][0], reg_array[0][1]); /* GP fault here */

fclose (file_handle);
0 Kudos
Message 3 of 7
(4,291 Views)
I haven't really looked at the code you submitted, but I do have some code that shows how to use the ArraytoFile and FiletoArray functions with statically allocated arrays:

#include
#include
#include
#include

#define COUNT 40

int main (int argc, char *argv[])
{
char pathname[260];
double myarray[40][40];
double newarray[40][40];
int i, j;

if (InitCVIRTE (0, argv, 0) == 0)
return -1; /* out of memory */

for (j=0;j for (i=0;i myarray[i][j] = (int)rand();
}
}

FileSelectPopup ("", "*.dat", "*.dat",
"Select file for Writing data to", VAL_LOAD_BUTTON,
0, 0, 1, 0, pathname);

ArrayToFile ("mydat.dat", myarray, VAL_DO
UBLE, 1600, 40,
VAL_GROUPS_TOGETHER, VAL_GROUPS_AS_COLUMNS,
VAL_CONST_WIDTH, 10, VAL_ASCII, VAL_TRUNCATE);

FileToArray ("mydat.dat", newarray, VAL_DOUBLE, 1600, 40,
VAL_GROUPS_TOGETHER, VAL_GROUPS_AS_COLUMNS, VAL_ASCII);

return 0;
}

I'm sure the problem with yours is in the logic of your mallocs and the proper selection of the grouping of the data items in the call to FileToArray (it has to match the makeup of your allocated block, otherwise it will try to write to memory that wasn't allocated for your process). Also FileToArray will not change the shape of your allocation, it will merely write into it in a manner that you hadn't expected.

Jason F.
Applications Engineer
National Instruments
www.ni.com/ask
0 Kudos
Message 4 of 7
(4,291 Views)
UPDATE TO PREVIOUS COMMENT, with info on how to use dynamic 2D arrays!

Actually, your question about dynamically allocated 2D arrays piqued my interest and I looked into making a working example of this myself.

If you want to dynamically allocate a 2D array in general, here are couple of ways to do it:

double **p2Din;

p2Din = malloc (NROWS * sizeof(double *));
for(i=0;i p2Din[i] = malloc(NCOLS * sizeof(double));

OR

double **p2Din;

p2Din = malloc (NROWS * sizeof(double *));
p2Din[0] = malloc (NROWS * NCOLS * sizeof(double));
for (i=1;i p2Din[i] = p2Din[0] + i * NCOLS;

The second method is more preferrable because it guarantees that the memory in the dynamic array is contiguous, whereas the multiple calls to malloc in the first method do not. I believe the first method is similar to yours (I didn't check to see if your code allocates correctly or not, but this one does).

IMPORTANT NOTE: The ArrayToFile and FileToArray functions require the memory of the array you pass in to be contiguous, because they will only dereference your 2D array pointer up to the pointer of the first row as the origin and perform block reads and writes from that point contiguously. If you use the first method of creating a dynamic 2D array your row pointers' memory locations may be interleaved with the array data, in which ArrayToFile and FileToArray will write and read to these locations possibly redirecting your pointers and causing the loss of memory and GPFs when the new pointer values are dereferenced.

Now, as far as the GPF you experienced in your code, this is most likely caused by the fact that you dereferenced a NULL pointer. In fact, you were correct, this was done by the FileToArray function, but only because the array was passed incorrectly to it.

In your code you passed "reg_array" as the pointer to the beginning of your array. Well, this is actually a pointer to the pointer to the beginning of the array, meaning that you should have passed "reg_array[0]" or "*reg_array". The incorrect passing basically caused your row pointers to be overwritten and the memory they pointed at to be lost forever :-O, when you called printf and passed it this new dereferenced address that probably didn't belong to your process, or better yet may not have been a valid address, the GPF occurred.

I have attached an example source file that uses a static 2D array, a dynamically allocated 1D array to simulate a 2D array, and a dynamically allocated 2D array with contiguous memory locations passed to the ArrayToFile and FileToArray functions to illustrate how to use them properly.

I hope this information helps.

Jason F.
Applications Engineer
National Instruments
www.ni.com/ask
0 Kudos
Message 5 of 7
(4,291 Views)
Jason, I'm glad your interest was piqued by my question. I wasn't able to run your example because the code to open a file to write or read were not present. But from looking at your reply, it looks like you answered my question. I WAS using the 'first' option to allocate memory, so most likely my data was not contiguous. I will try the 2nd way as you explained. Only other question is why in your example the number of 'groups' changes from 40 (in Array to File) to 1 (in File to Array)? See below. Thanks a lot!

---------------
ArrayToFile (pathname, p2Din[0], VAL_DOUBLE, 1600, 40, VAL_GROUPS_TOGETHER, VAL_GROUPS_AS_COLUMNS,
VAL_CONST_WIDTH, 10, VAL_ASCII, VAL_TRUNCATE);

FileToArray (pathname, p2Dout[0], VAL_DOUBLE, 1600, 1,
VAL_GROUPS_TOGETHER, VAL_GROUPS_AS_COLUMNS, VAL_ASCII);
0 Kudos
Message 6 of 7
(4,291 Views)
I accidentally set it to 1, it should really be 40 in both, or at least the same in both because this really only effects the ordering of the data in your logical rows and columns. I have attached the revised example to this post.

Jason F.
Applications Engineer
National Instruments
www.ni.com/ask
0 Kudos
Message 7 of 7
(4,291 Views)