LINUX.ORG.RU

Как узнать количество прочитанных байт?

 


0

1

Собственно, сабж. Есть код

FILE* cmd = popen("hostname", "r");
len = fread(buf, 100, 1, cmd);
    if (len > 0)
        что-то делаем

    pclose(cmd);

Почему-то в len всегда возвращается 0, хотя данные прочитаны . Почему так?

Оно не в байтах возвращает, а в итемах. Видимо, у тебя этот hostname меньше чем 100 байт.

man fread:

On success, fread() and fwrite() return the number of items read or written. This number equals the number of bytes transferred only when size is 1. If an error occurs, or the end of the file is reached, the return value is a short item count (or zero).

CrX ★★★★★
()
Последнее исправление: CrX (всего исправлений: 1)

fread читает кусками, размером <первый числовой аргумент> и количеством <второй числовой аргумент>. Возвращает число прочитанных полных кусков. Ты читаешь один кусок размером 100 байт.

anonymous
()
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>

int main(int argc, char *argv[])
{
    FILE * f = popen("hostname","r");
    char buff[2048];
    assert(fscanf(f,"%2047s",&buff));
    printf("Байт прочитано %d -> %s\n",strlen(buff),buff);
    pclose(f);
    return 0;
}
dron@gnu:~/Рабочий-стол/ыфваыфв$ gcc main.c && ./a.out 
Байт прочитано 3 -> gnu
dron@gnu:~/Рабочий-стол/ыфваыфв$
LINUX-ORG-RU ★★★★★
()
Ответ на: комментарий от LINUX-ORG-RU

У тебя тут не прочитано байт, а длина строки. Более того, нулевой байт оно не учитывает. Почему бы просто не использовать read(2)? Он как раз возвращает число прочитанных байт.

u5er ★★
()
Ответ на: комментарий от u5er

Я забыл полнулять, тогда бы было 0 если данные не прочитались и Nбайт равное прочитанному если почитались, имя хоста может сожержать пробел через экранирование? Вроде нет.

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>

int main(int argc, char *argv[])
{
    FILE * f = popen("hostname","r");
    char buff[2048];
+   memset(buff,0,sizeof(buff));
    assert(fscanf(f,"%2047s",&buff));
    printf("Байт прочитано %d -> %s\n",strlen(buff),buff);
    pclose(f);
    return 0;
}
LINUX-ORG-RU ★★★★★
()
Последнее исправление: LINUX-ORG-RU (всего исправлений: 1)
Ответ на: комментарий от LINUX-ORG-RU

Вот мой велосипед

#include <stdio.h>
#include <unistd.h>

#define BUF_SIZE 1024

int main( int argc, char* argv[], char* envp[] ){
	
	FILE* f;
	char buf[BUF_SIZE];
	int fd;
	ssize_t bytes;
	
	f = popen( "hostname","r" );
	if( !f ){
		perror( "popen" );
		return 1;
	}
	
	fd = fileno( f );
	
	bytes = read( fd, buf, BUF_SIZE - 1 );
	if( bytes < 0 ) {
		perror( "read" );
	} else {
		buf[bytes] = 0x00;
		printf( "Байт прочитано %li -> %s\n", bytes, buf );
	}
	
	pclose(f);
	return 0;
	
}

u5er ★★
()
Ответ на: комментарий от zer0cat
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>

int main(int argc, char *argv[])
{
    FILE * file = popen("head -c 5 /dev/random","r");
    char   buff[2048];
    char   run  = 1;
    size_t size = 0;
    while(run && size < sizeof(buff))
    {
       run = fread(&buff[size++],1,1,file);
    }
    printf("Байт прочитано %zu -> %s\n",size,buff);
    for (int i = 0; i < size; i++)
    {
        printf("[%d][%d] %d \n",i,i+1,buff[i]);
    }
    pclose(file);
    return 0;
}
dron@gnu:~/Рабочий-стол/ыфваыфв$ gcc main.c && ./a.out 
Байт прочитано 6 -> Cd��<
[0][1] 67 
[1][2] 100 
[2][3] -2 
[3][4] -51 
[4][5] 60 
[5][6] 0 
dron@gnu:~/Рабочий-стол/ыфваыфв$ 
LINUX-ORG-RU ★★★★★
()
Ответ на: комментарий от u5er

У меня нет предположений. Я просто предположил, что ТС использует fread как раз потому, что весь интернет заполонён воем про небезопасность функций stdlib без f спереди. Даже если они лучше всего подходят для задачи.

anonymous
()
#include <stdio.h>

long g_lFileSize, g_lFilePos;

int IsEndOfFile(FILE* stream)
{
	g_lFilePos = ftell(stream);
	fseek(stream, 0, SEEK_END);
	g_lFileSize = ftell(stream);
	fseek(stream, g_lFilePos, SEEK_SET);
	if (g_lFilePos >= g_lFileSize)
		return 0;
	return 1;
}

long filesize(FILE* stream)
{
	long curpos, length;
	curpos = ftell(stream);
	fseek(stream, 0, SEEK_END);
	length = ftell(stream);
	fseek(stream, curpos, SEEK_SET);
	return length;
}

int main(int argc, char **argv)
{
	FILE* cmd;
	char buf[100];
	float count, percent;
	count = percent = 0;
	g_lFileSize = g_lFilePos = 0;

	cmd = popen("hostname", "rb");

	while (IsEndOfFile(cmd))
	{
		if (fread(buf, 100, 1, cmd))
		{
			count += 100;
			percent = (count / g_lFileSize) * 100;
			printf("Done %1.f%\r", percent);
		}
	}
	fclose(cmd);
	return 0;
}

anonymous
()
Ответ на: комментарий от anonymous

весь интернет заполонён воем про небезопасность функций stdlib без f спереди

У тебя какой-то странный интернет, видимо ты сидишь в какой-то соцсети и подписан там на идиотов, которые тебе это пишут. В нормальных местах такого быть не могло.

firkax ★★★★★
()
Ответ на: комментарий от anonymous

Хватит бредить и избавляйся от дрочения на комитеты. read() это нативный способ чтения файлов, а fread бажная обёртка над ним. Его может быть нет разве что в винде (и то не уверен), но помощь по проганию под винду тут не оказывается.

firkax ★★★★★
()

https://sourceware.org/git/?p=glibc.git;a=blob;f=libio/iofread.c

если выкинуть всю лабуду, то

size_t
_IO_fread (void *buf, size_t size, size_t count, FILE *fp)
{
  size_t bytes_requested = size * count;
  size_t bytes_read = read(fp, (char *) buf, bytes_requested);
  return bytes_requested == bytes_read ? count : bytes_read / size;
}

у тебя size = 100. ты прочитал, к примеру, 99 ну и соответственно получаешь 99/100. что для size_t = 0. Как уже было сказано, ты перепутал местами 100 и 1. Ну и для ошибок и конца нужно использовать функции ferror и feof. len > 0 - это багокод, что ты и обнаручил.

vtVitus ★★★★★
()
Ответ на: комментарий от bugfixer

плевок в лицо майнтейнерам libc.
Ссылки на конкретные баги

Он - bsd’шник. У них своя libc. Там есть вот такие приколы, которые могут быть не пофикшены добрых 15+ лет, пока кто-нибудь не скопирует фикс из другой *BSD . У него, как и у любого лонг-тайм bsd’шника PTSD.

LamerOk ★★★★★
()
Ответ на: комментарий от bugfixer

Я не про реализацию а про спецификацию. API fread-а вынуждает городить вокруг него костыли, которые систематически провоцируют баги, и от ОС это не зависит.

Впрочем и то, что на ровном месте городятся какие-то обёртки (даже если бы она была одна - сам fread), это тоже почти баг.

firkax ★★★★★
()
Последнее исправление: firkax (всего исправлений: 1)
21 сентября 2024 г.
Ответ на: комментарий от bugfixer

Опять столкнулся со странной ошибкой этого самого fread. Вроде все хорошо делаю. Простой пример, читаем данные и перезаписываем их назад поблоков. Уходит в бесконечный цикл..

Корректно читает 1, 2, 3 мегабайты, а дальше начинается бред.

#define BLOCK_SIZE 1024*1024
int badread(const char* file_name)
{
	FILE* f = NULL;
	size_t dwWR = 0;
	uint64_t pos = 0;


	f = fopen(file_name, "r+b");
	if (f != NULL)
	{
		uint8_t* lpBuf = malloc(BLOCK_SIZE);
		memset(lpBuf, 0, BLOCK_SIZE);

		do
		{
			dwWR = fread(lpBuf, sizeof(uint8_t), BLOCK_SIZE, f); //размер элемента, к-тво элементов

			if (dwWR == 0) break;

			pos = dwWR;
			fseek(f, -pos, SEEK_CUR);

			if ((fwrite(lpBuf, sizeof(uint8_t), dwWR, f)) != dwWR)
			{
				puts("fwrite");
				break;
			}

		} while (!feof(f));

		FREE(lpBuf);

		fclose(f);

	}

	return 1;
}
zer0cat
() автор топика
Последнее исправление: zer0cat (всего исправлений: 1)
Ответ на: комментарий от unDEFER

Ни в коем случае. «+» это уже write.

Упс. Действительно - поторопился я, не стОит так делать.

Но эффект действительно интересный - проблемы начинаются на первом fwrite() после fseek() после того как в EOF упёрлись. И вылазит это на RHEL в том числе, так что отползти сославшись на «условно-васянскую» сборку libc не получится. Придётся ковырять дальше…

bugfixer ★★★★★
()