LINUX.ORG.RU

Встроить текстовый файл в прогу на C++


0

0

У меня есть текстовый файл. Хочу встроить его в свою программу на С++, чтобы в рантайме к этому тексту можно было обратиться как к char *.

Должно работать на Линуксе и винде, не требовать ручной модификации файла, встраиваться в процесс компиляции программы.

Как такое можно сделать?

Заранее спасибо за помощь.


Может так же как в qt ресурсы сделаны - просто дописать в бинарнике в конец файла то что тебе нужно? )

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

а дальше открыть файл, перемотать до этого места и прочитать?

alius
()

char *resource = (char *){
"line 1\n",
"line 2"
};

А что если примерно так?

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

$ cat data.txt
Hello world

$ objcopy --input binary --output elf32-i386 --binary-architecture i386 data.txt data.o

$ gcc main.c data.o

$ cat main.c
#include <stdio.h>

extern char _binary_data_txt_start;
extern char _binary_data_txt_end;

main()
{
char* p = &_binary_data_txt_start;

while ( p != &_binary_data_txt_end ) putchar(*p++);
}

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

> Может так же как в qt ресурсы сделаны - просто дописать в бинарнике в конец файла...

Это ты где такое почерпнул?

mannaz
()

> Должно работать на Линуксе и винде, не требовать ручной модификации файла, встраиваться в процесс компиляции программы.

Тебе нужно чтобы именно процесс преобразования текстового файла при компиляции работал на венде?

Я как-то писал велосипед на шелле, который преобразовывал любой файл (бинарный, не обязательно текст) в программу на C: http://www.linux.org.ru/view-message.jsp?msgid=3140778. Может подойдёт.

Deleted
()

base64 - и храни хоть текст, хоть архивы, хоть картинки и т.п., если хочешь скопипастю две функции для кодирования/декодирования

lester ★★★★
()

> встраиваться в процесс компиляции программы.

тоже не сложно - думаю как перед сборкой добавить несколько строк для проверки файла на обновление, конвертацию в base64 и запихивание в отдельный .h файл объяснять не надо

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

Если под виндой подразумевается визуальная студия, то использовать виндовые ресурсы

если нет, то точно также (как уже сказали выше cygwin или любая другая сборка)

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

кстати objcopy можно прикрутить и к студии, coff она вроде умеет

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

> только файл в base64 занимает на треть больше. просто я подумал, что base64 в любом случае полезно будет иметь...

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

хз

base64 тебе придется читать, декодировать и хранить в памяти

а если сделать objcopy, то (по крайней мере в никсах) будет mmap...

(конечно если файл маленький, то можно забить на эти отличия)

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

//////////////////////////////////////////////////////////////////////////
#pragma mark base64
#pragma mark -
//////////////////////////////////////////////////////////////////////////

/**********************************************************************************************/
uchar base64table[ 256 ] =
{
	64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
	64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
	64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63,
	52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64,
	64,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
	15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64,
	64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
	41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64,
	64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
	64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
	64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
	64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
	64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
	64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
	64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
	64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
};

/**********************************************************************************************/
char base64chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

/**********************************************************************************************/
size_t base64encode( void* outPtr, const void* dataPtr, size_t size )
{
	uchar* out = (uchar*) outPtr;
	uchar* start = out;
	const uchar* data = (const uchar*) dataPtr;

	size_t i = 0;
	for( ; i < size - 2 ; i += 3 )
	{
		*out++ = base64chars[ ( data[ i ] >> 2 ) & 0x3F ];
		*out++ = base64chars[ ( ( data[ i ] & 0x3 ) << 4 ) | ( (int) ( data[ i + 1 ] & 0xF0 ) >> 4 ) ];
		*out++ = base64chars[ ( ( data[ i + 1 ] & 0xF ) << 2 ) | ( (int) ( data[ i + 2 ] & 0xC0 ) >> 6 ) ];
		*out++ = base64chars[ data[ i + 2 ] & 0x3F ];
	}

	if( i < size )
	{
		*out++ = base64chars[ ( data[ i ] >> 2 ) & 0x3F ];
		if( i == size - 1 )
		{
			*out++ = base64chars[ ( ( data[ i ] & 0x3 ) << 4 ) ];
			*out++ = '=';
		}
		else 
		{
			*out++ = base64chars[ ( ( data[ i ] & 0x3 ) << 4 ) | ( (int) ( data[ i + 1 ] & 0xF0 ) >> 4 ) ];
			*out++ = base64chars[ ( ( data[ i + 1 ] & 0xF ) << 2 ) ];
		}
		*out++ = '=';
	}

	return out - start + 1;
}

/**********************************************************************************************/
size_t base64decode( void*& outPtr, const void* dataPtr, size_t size )
{
	size_t res = ( ( size + 3 ) / 4 ) * 3;
	outPtr = malloc( res + 1 );
	uchar* out = (uchar*) outPtr;
	const uchar* data = (const uchar*) dataPtr;

	while( size > 4 )
	{
		*(out++) = base64table[ data[ 0 ] ] << 2 | base64table[ data[ 1 ] ] >> 4;
		*(out++) = base64table[ data[ 1 ] ] << 4 | base64table[ data[ 2 ] ] >> 2;
		*(out++) = base64table[ data[ 2 ] ] << 6 | base64table[ data[ 3 ] ];

		data += 4;
		size -= 4;
	}

	if( size > 1 )
		*(out++) = base64table[ data[ 0 ] ] << 2 | base64table[ data[ 1 ] ] >> 4;
	if( size > 2 )
		*(out++) = base64table[ data[ 1 ] ] << 4 | base64table[ data[ 2 ] ] >> 2;
	if (size > 3)
		*(out++) = base64table[ data[ 2 ] ] << 6 | base64table[ data[ 3 ] ];

	res -= ( 4 - size ) & 3;
	return res;
}



encode - перегнать блок памяти в строку, decode - назад, 

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

> base64 тебе придется читать, декодировать и хранить в памяти

изредка пользуюсь им потому-что собираю свои проекты разными компиляторами на разных ОС, да и небольшие данные( например иконка 16х16 в PNG с альфа каналом для гуи ) занимают три строки в коде и легко удаляются/переносятся

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

> тебе придется читать, декодировать

для тех же картинок у меня есть свой класс Bitmap, чей конструктор без проблем "ест" текст в base64, так что ни одной лишней новой строки не надо писать

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

Что-то как-то сложно имхо.

Пишем прогу, она создаёт хидер перед компиляцией.

#include <stdio.h>

int main() {
	FILE* f = fopen( "file.txt", "r" );
	FILE* fo = fopen( "file_txt.h", "a" );
	
	char p[] = "const char file_txt[] = {";
	char e[] = "0x00};";

	fwrite( p, 1, sizeof( p ), fo );

	int c = fgetc( f );
	
	do {
		fprintf( fo, "0x%X,", c );
		c = fgetc( f );
	} while( c != EOF );

	fwrite( e, 1, sizeof( e ), fo );
	fclose( f );
	fclose( fo );

	return 0;
}

Инклюдим в основную программу:

#include <stdio.h>
#include "file_txt.h"

int main() {
	printf( file_txt );
	return 0;
}

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

> Что-то как-то сложно имхо.

главный плюс - компактность в коде, если надо запихнуть например 20 мелких файлов в один хедер, то base64 будет смотреться компактно и опрятно, в отличие от такого кодирования как у вас

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

#include <stdio.h>

int main() {
	FILE* f = fopen("file.txt", "r");
	FILE* fo = fopen("file_txt.h", "a");
	
	char p[] = "const char file_txt[] = {";
	char e[] = "0x00};";

	fwrite( p, 1, sizeof( p ) - 1, fo );

	int c = fgetc( f );
	
	do {
		fprintf( fo, "0x%X,", c );
		c = fgetc( f );
	} while( c != EOF );

	fwrite( e, 1, sizeof( e ) - 1, fo );
	fclose(f);
	fclose(fo);

	return 0;
}

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

> А что в них смотреть то?

все просто - там где надо положить один файл как ресурс, вполне вероятно понадобится положить еще 20, создавать 20 хедеров для небольших файлов - несерьезно, значит будет все записывать в один - а вы ж понимаете, что вполне вероятно, что прийдется не раз добавлять/удалять/изменять некоторые из вложенных файлов

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

вобщем мое мнение субъективно и ваш вариант несомненно лучше в плане скорости

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

>не раз добавлять/удалять/изменять некоторые из вложенных файлов

Ну да, пересоздавать всё тогда. Но это очень быстро.

The красота & компактность edition:

#include <stdio.h>

int main() {
	FILE* f = fopen( "file.txt", "r" );
	FILE* fo = fopen( "file_txt.h", "a" );
	
	char p[] = "const char file_txt[] = {\n   ";
	char e[] = "0x00\n};\n";

	fwrite( p, 1, sizeof( p ) - 1, fo );

	int c = fgetc( f ), cnt = 0;	
	
	do {
		fprintf( fo, "0x%X,", c );
		if( ++cnt == 16 ) {
			fprintf( fo, "\n   " );
			cnt = 0;
		}
		c = fgetc( f );
	} while( c != EOF );

	fwrite( e, 1, sizeof( e ) - 1, fo );
	fclose( f );
	fclose( fo );

	return 0;
}

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

> не раз добавлять/удалять/изменять некоторые из вложенных файлов

make

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

>На perl'е короче

Ради интереса сравнил, чего это стоит. Создал двухмеговый блоб и прогнал через этот перловый скрипт.

~/src/tmp$ time ./pl2

real    0m2.194s
user    0m2.085s
sys     0m0.040s

И через сишную:

~/src/tmp$ time ./a

real    0m0.337s
user    0m0.290s
sys     0m0.028s

На всякий случай проверил таким скриптом:

#!/usr/bin/perl

open( DATA, "<file.txt" );
open( OUT, ">>file_txt.h" );
print OUT "const char *txt = {\n";
while( $c = getc( DATA ) ) {
	printf OUT "0x%X, ", ord( $c );
}
print OUT "0x00};\n";

Да, быстрее:

~/src/tmp$ time ./pl3

real    0m1.909s
user    0m1.854s
sys     0m0.026s

Либо я не знаю все хитрости перла, либо он тут sukk больше чем в 5 раз.

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

Каждый раз при изменении ресурсов она выполняется.

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

> Создал двухмеговый блоб и прогнал через этот перловый скрипт.

ИМХО - 2Мб уже не тот размер, чтоб включать его таким образом прямо в код, в вашем варианте будет файл в 12Мб - компилятор заикаться будет на ребилдах

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

> Либо я не знаю все хитрости перла

data.o: data.txt
    perl -Mbytes -E'say"const char*txt={\n",(map{s/./ord($$&).",".(++$$lf&15?"":"\n")/gse;$$_}<>),"0};"' $< >$@

вот вся «хитрость» перла. необходима обработка больших объёмов данных — С вам в руки.

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

>> так что ни одной лишней новой строки не надо писать

я не имел в виду, что придется все делать руками)

а по поводу иконок, почему не xpm? хавается сишным компилятором, не требует декодирования...

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

> а по поводу иконок, почему не xpm? хавается сишным компилятором, не требует декодирования...

иконки без альфа канала - прошлый век :)

lester ★★★★
()

$ cat 1.txt 
hello
$ xxd -i 1.txt 
unsigned char __1_txt[] = {
  0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x0a
};
unsigned int __1_txt_len = 6;
$ which xxd
/usr/bin/xxd
$ apt-file search /usr/bin/xxd
vim-common: /usr/bin/xxd
vim-dbg: /usr/lib/debug/usr/bin/xxd
xxdiff: /usr/bin/xxdiff

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

> не два, а четыре ;) print и \n кстати, интересно, а в каких дистрибутивах ещё 5.8.х?

Мне и 4 не жалко. v5.8.8 в Debian oldstable (etch), еще поддерживается.

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

>А под винду как?

mingw32 и

objcopy --input binary --output pe-i386 --binary-architecture i386 --prefix-symbols=_data.txt data.o

Так что в мейкфайле должны быть извращения для win32 с --prefix-symbols, которые для *nix не нужны.

linuxfan
()

А через маппирование памяти в файл - не кошерно?

Eddy_Em ☆☆☆☆☆
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.