LINUX.ORG.RU

Оно не в байтах возвращает, а в итемах. Видимо, у тебя этот 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
()
Ответ на: комментарий от anonymous

Нет, естественно, предложений.

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
()

Во-первых, правильный синтаксис fread такой:

len = fread(buf, 1, sizeof(buf), fp);
Во-вторых, откуда ты знаешь что данные прочитаны когда он вернул 0?

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

Что ты несёшь? read(2) это как раз наиболее подходящая штука для чтения байт из файлового дескриптора. Всё остальное вызывает тоже её внутри.

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

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

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

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

Тебе этот пример дали там же где фантазируют про опасность read()? Какой ещё seek на пайп?

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

Ни разу не видел. Конкретика есть какая-нибудь или они только вой подымают?

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

Всё остальное вызывает тоже её

не, ещё readv() вызывают

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

Во-вторых, откуда ты знаешь что данные прочитаны когда он вернул 0?

Смотрю в отладчике

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

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

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

Ну конечно read нет под виндой, а CRT везде есть.

zer0cat
() автор топика

1 и 100 местами поменяй

Reset ★★★★★
()

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 ★★★★★
()
Ответ на: комментарий от firkax

а fread бажная обёртка над ним.

Сильно. Хороший такой плевок в лицо майнтейнерам libc. Ссылки на конкретные баги, конечно, последуют?

bugfixer ★★★★★
()
Ответ на: комментарий от 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)
Ответ на: комментарий от zer0cat

Добавил fflush после fwrite и вроде заработало.

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

надо просто обертку на расте написать. сразу станет сисюрно. обсисюрить такскаать…

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

Вроде все хорошо делаю… fopen(file_name, "r+b");

Не мешало бы файл в «w+b» режиме открыть если мы туда писать собираемся.

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

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

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

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

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

я на С пишу

Соболезную. Переходи на c++. Там есть тормозные стримы.

ox55ff ★★★★★
()
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.