Почему выводит неполную информацию о файле изображения?
Тут странная ситуация с программой выходит: Если вводить текст вручную или подавать его из файла, то информация выводится как надо. Если же попытаться загрузить информацию из файла изображения xxx.jpg, то почему-то печатает только первые четыре байта, хотя информацию передаёт и записывает как следует. То есть на выходе получается тоже изображение.
Я думал, что он грешит на 00 в HEX данных изображения, но информацию передаёт нормально, только не выводит её почему-то...
Извиняюсь за польский, но думаю, что не критично.
Вот код:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#define READ 0
#define WRITE 1
#define N 10000000
char string[N];
char hex[2*N];
void clear(char *tab, int par)
{
int i;
for(i = 0; i < par; i++)
{
tab[i] = 0;
}
}
void clear_stdin()
{
int c;
while ((c = getchar()) != '\n' && c != EOF){
continue;
}
}
char plik_read(char* string, int par)
{
FILE *file;
char ADRES[256];
printf("Wpisz adres pliku razem z formatem! \n");
fflush(stdout);
if (strchr(ADRES, '\n') == NULL) {
clear_stdin();
}
if (fgets(ADRES, 256, stdin) == NULL) {
/* Ma miejsce błąd lub został przeczytany EOF */
}
else {
/* Usuwamy symbol końca wierza */
size_t last = strlen(ADRES) - 1;
if (ADRES[last] == '\n')
ADRES[last] = '\0';
/* Tutaj można przeanalizować wiersz */
}
printf("\n\n");
if ((file = fopen(ADRES, "r+")) == NULL)
{
printf("Nie udalo sie otworzyc pliku, uruchom ponownie! \n");
_exit(0);
}
else
{
int i = 0;
while(!feof (file) && i<par) {
if (fread(string , sizeof(char), par, file))
{
printf("%s", string);
i += par;
}
}
fclose(file);
}
return *string;
}
char plik_write(char* string, int par)
{
int fp;
fp = creat("file.dat", S_IREAD|S_IWRITE);
if (fp == -1)
{
printf ("Nie moge utworzyc file.dat \n");
_exit(0);
}
write (fp, string, par);
close (fp);
return *string;
}
int main()
{
if(fork() == 0)
{
char c='N';
printf("Dane znajduja sie w pliku? Y/N? --> ");
fflush(stdout);
scanf ("%c", &c);
printf("\n");
if(c=='Y')
{
c='N';
printf("To jest /dev/urandom ? Y/N? --> ");
clear_stdin();
scanf ("%c", &c);
if (c == 'Y')
{
int U;
printf("Podaj liczbe odczytanych bajtow: ");
scanf ("%d", &U);
plik_read(string, U);
printf("\n\n");
plik_write(string, U);
clear(string, U);
}
else
{
plik_read(string, N);
printf("\n\n");
plik_write(string, N);
clear(string, N);
}
}
else
{
printf("Wpisz tekst: \n\n");
fflush(stdout);
if (strchr(string, '\n') == NULL) {
clear_stdin();
}
fgets(string, N, stdin);
printf("\n");
plik_write(string, N);
clear(string, N);
//~ for(int i=0; i<strlen(string); i++)
//~ printf("%c", string[i]);
}
/* tablica przechowujaca uchwyty na pliki odczytu i zapisu */
int pdes[2];
/* tworzymy pipe skladajaca sie z uchwytu do plikow do odczytu
* i do zapisu (R i W); deskryptory zostana umieszczone w tablicy */
pipe(pdes);
if(fork() == 0)
{
FILE *fp;
/* zamykamy niepotrzebny deskryptor */
close(pdes[READ]);
sleep(1);
fp = fopen("file.dat", "r+");
while(!feof (fp)) {
if (fread(string , sizeof(char), N, fp))
printf("%s \n", string);
}
fclose(fp);
int len = strlen(string);
// Konwertowanie string to hex
for (int i = 0, j = 0; i < len; ++i, j += 2)
sprintf(hex + j, "%02x", string[i] & 0xff);
printf("%s \nin hex is \n%s\n\n", string, hex);
clear(string, N);
/* wysylamy podany ciag znakow przez pipe */
write(pdes[WRITE], hex, strlen(hex));
}
else
{
if(fork()==0)
{
/* zamykamy niepotrzebny deskryptor */
close(pdes[WRITE]);
/* odbieramy cag znakow z pipe */
read(pdes[READ], hex, sizeof(hex));
int len = strlen(hex);
for (int i=0, j=1; i<len; j++)
{
fprintf(stderr, "%c%c ", hex[i], hex[i+1]);
if(j==15)
{
fprintf(stderr, "\n");
j = 0;
}
i+=2;
}
clear(hex, 2*N);
}
}
}
for(;;)
pause();
return 0;
}
Вот HEX данные изображения:
Вот результат работы программы (изображение на выходе нормальное):

Ответы (1 шт):
Посмотрим на эти строки
int len = strlen(string);
// Konwertowanie string to hex
for (int i = 0, j = 0; i < len; ++i, j += 2)
sprintf(hex + j, "%02x", string[i] & 0xff);
printf("%s \nin hex is \n%s\n\n", string, hex);
В string хранится собственно массив с данными. strlen считает размер до первого нулевого символа (а он в этом массиве 5, если смотреть на картинку дампа). Поэтому, цикл и работает до 4. И выводит только 4 байта.
Давайте пофиксим минимальными жертвами. fread возвращает кол-во прочитанных "объектов", что в нашем случае равно количеству байт. sizeof(char) обычно равен 1 (в с++ с этим строго-строго, а вот о си я не знаю точных гарантий).
int len = fread(string , sizeof(char), N, fp)
fclose(fp);
// теперь len хранит реальный размер в байтах
// Konwertowanie string to hex
for (int i = 0, j = 0; i < len; ++i, j += 2)
sprintf(hex + j, "%02x", string[i] & 0xff);
printf("%s \nin hex is \n%s\n\n", string, hex);
clear(string, N);
также там дальше используется strlen, где можно было бы размер и так посчитать
--- upd ---
как вывести весь файл в консоль в хекс виде
#include <stdio.h>
int main()
{
FILE* f= fopen("/etc/hosts", "r");
if (!f) {
perror("no file");
return -1;
}
char b[1];
while(fread(b, sizeof(b), 1, f)) {
printf("%02X ", b[0]);
}
fclose(f);
}
да, способ не очень эффективный, но для понимания подойдет. Лучше читать кусками по 4-8 килобайт.
