问题
I need to convert a text file of the following format to binary:
The first line contains the number of products in the inventory, The following lines contains:
product name '\t'
product price '\t'
quantity '\n'
(there can be more than one \t between columns)
For every product the binary output file will contain an int representing the length of the product name, the chars that hold the product name, an int representing the price and an int representing the quantity.
Sample input file:
Asus Zenbook 1000 10
iPhone 5 750 22
Playstation 4 1000 0
I have wrote the following code, and I understood that I'm supposed to see the string in plain text while the integers will show up as gibberish (in binary):
int convertTextToBinary(char *fileName)
{
FILE *pText, *pBinary;
int size, i;
char *currProdName;
int currProdNameLen, currQuantity, currPrice;
if (checkFileExists(fileName) == FALSE)
{
printf("- Given file does not exists!\n");
return ERROR;
}
else
pText = fopen(fileName, "r");
// get the number of products in the inventory
fscanf(pText, "%d", &size);
#ifdef DBG
printf("##DBG Successfuly read &size = %d DBG##\n", size);
#endif
pBinary = fopen(strcat(fileName, ".bin"), "wb");
fwrite(&size, sizeof(int), 1, pBinary);
#ifdef DBG
printf("##DBG Successfuly wrote &size = %d DBG##\n", size);
#endif
for (i = 0; i < size; i++)
{
// get product name and name length
currProdNameLen = getProdName(pText, &currProdName);
#ifdef DBG
printf("##DBG %d Successfuly read &currProdName = %s DBG##\n", i+1, currProdName);
printf("##DBG %d Successfuly read &currProdNameLen = %d DBG##\n", i+1, currProdNameLen);
#endif
// get product price
fscanf(pText, "%d", &currPrice);
printf("##DBG %d Successfuly read &currPrice = %d DBG##\n", i+1, currPrice);
// get product quantity
fscanf(pText, "%d", &currQuantity);
printf("##DBG %d Successfuly read &currQuantity = %d DBG##\n", i+1, currQuantity);
// write data to binary file
fwrite(&currProdNameLen , sizeof(int), 1, pBinary);
fwrite(&currProdName, sizeof(char), currProdNameLen, pBinary);
fwrite(&currPrice, sizeof(int), 1, pBinary);
fwrite(&currQuantity, sizeof(int), 1, pBinary);
free(currProdName);
}
fclose(pText);
fclose(pBinary);
return 1;
}
/* This function checks if a file in a given path exists or not by using fopen with "read" argument */
BOOL checkFileExists(char *fileName)
{
FILE *fp;
fp = fopen(fileName, "r");
// file does not exists
if (fp == NULL)
return FALSE;
// file does exists
else
{
fclose(fp);
return TRUE;
}
}
int getProdName(FILE *fp, char **prodName)
{
int nameLen = 0, offset;
// count the length of the product name
while (fgetc(fp) != '\t')
nameLen++;
// allcoate memory for the product name
*prodName = (char*)malloc(sizeof(char)*nameLen);
//checkalloc(&prodName);
// get the cursor back to the original position
offset = -1 * nameLen;
fseek(fp, offset, SEEK_CUR);
// copy product name from text to string
fgets(*prodName, nameLen, fp);
return strlen(*prodName);
}
But the hell, my output file looks like this:
¨ ּּּּּט ¨ ּּּ¯ ¨ ּּּּּּּּ ּּּ«
¨
Which holds no plain text. I have tried changing the fopen argument from "wb" to "w" but I still get gibberish files. What am I doing wrong?
回答1:
Here you write the pointer and additional garbage instead of the string it points to:
fwrite(&currProdName, sizeof(char), currProdNameLen, pBinary);
You should use:
fwrite(currProdName, sizeof(char), currProdNameLen, pBinary);
In your version you are passing the pointer to the pointer, but you want to pass the pointer itself.
BTW: In your function getProdName()
, you should add an additional character, because you are allocating the exact string lenght, but no room for the 0
Byte at the end. This can also cause problems. Also fgets
reads one char less. Check the man page for fgets
. Instead of using fgets
, you can also use fread
because you know the length anyway. No additional parsing needed.
update
Change this:
fscanf(pText, "%d", &currQuantity);
to
fscanf(pText, "%d\n", &currQuantity);
来源:https://stackoverflow.com/questions/18303166/converting-text-to-a-binary-file