Kopírování dat z jednoho souboru do druhého – C / C++ – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

Kopírování dat z jednoho souboru do druhého – C / C++ – Fórum – Programujte.comKopírování dat z jednoho souboru do druhého – C / C++ – Fórum – Programujte.com

 

PiranhaGreg0
Stálý člen
23. 4. 2015   #1
-
0
-

Zdravím,

rozděluji jeden obří soubor na hodně malých. Vždy předem vím kolik dat načíst a přeuložit je do nového souboru. Jak to zařídit co nejrychleji v C nebo C++?

Mě napadá akorát načíst ty data do bufferu a poté je z něj zase zkopírovat do výstupního souboru. Což je min. jedno zbytečný kopírování. Já bych potřeboval něco ve smyslu input >> output s možností zvolit si velikost.

Nahlásit jako SPAM
IP: 109.81.210.–
PiranhaGreg0
Stálý člen
23. 4. 2015   #2
-
0
-

#1 PiranhaGreg
Na linuxu je na to hezká funkce, kterou bych přesně uměl využít. Raději bych ale něco ze standardních knihoven...

Nahlásit jako SPAM
IP: 109.81.210.–
ondrej39+1
Věrný člen
24. 4. 2015   #3
-
0
-

#2 PiranhaGreg
Data načítáš po řádcích, nebo jakým způsobem? Pokud jo, normální fstream ti nevyhovuje? By sis mohl otevřít dva soubory, původní velký a nový malý, nový otevřít přes std::ios::app a pomocí getline z velkého do malého načítat data.

Nicméně ti tady vzniká problém, že budeš muset mít uloženou pozici posledního kopírovaného řádku a k tomuto řádku se budeš muset při tvorbě dalšího kopírování do druhého malého souboru (pravděpodobně přes for cyklus) prokousat.

Nahlásit jako SPAM
IP: 46.39.172.–
Inject all the dependencies!
ondrej39+1
Věrný člen
24. 4. 2015   #4
-
0
-

Možná ti toto pomůže.

#ifndef FILEHANDLER_H
#define FILEHANDLER_H

#include <fstream>
#include <string>
#include <algorithm>

class FileHandler
{
public:
	FileHandler(const std::string& fileName)
	{
		_inputFile.open(fileName.c_str());

		if (_inputFile.fail())
		{
			throw std::strerror(errno);
		}

		_lastReadLine = 1;
		_linesCount = countLines();
	}
	__int64 countLines()
	{		
		return (std::count(std::istreambuf_iterator<char>(_inputFile),
			std::istreambuf_iterator<char>(), '\n') + 1);
	}
	void ParseFile(const std::string& filename)
	{
		std::ofstream outputFile;
		outputFile.open(filename, std::ios::app);

		GotoLine(_inputFile, _lastReadLine);
		
		std::string line;
		_inputFile >> line;

		if (line != "")
		{
			outputFile << line + "\n";
		}

		++_lastReadLine;
		outputFile.close();
	}
	std::ifstream& GotoLine(std::ifstream& file, int num)
	{
		file.seekg(std::ios::beg);
		for (int i = 0; i < num - 1; ++i)
		{
			file.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
		}
		return file;
	}
	~FileHandler()
	{
		_inputFile.close();
	}
protected:
private:
	std::ifstream _inputFile;
	__int64 _linesCount;
	int _lastReadLine;
};

#endif
Nahlásit jako SPAM
IP: 46.39.172.–
Inject all the dependencies!
JoDiK
~ Anonymní uživatel
987 příspěvků
24. 4. 2015   #5
-
0
-

#3 ondrej39
Jaké řádky? O typu souboru nic nepsal, takže to může být jakýkoliv binární soubor. Řádky jsou jen v textových souborech...

Nahlásit jako SPAM
IP: 88.103.236.–
JoDiK
~ Anonymní uživatel
987 příspěvků
24. 4. 2015   #6
-
0
-

#1 PiranhaGreg
Jinak než načtením do bufferu a zápisem do nového souboru (souborů) to nejde, takže nevím nad čím bádáš... Nejrychleji se to odjakživa dělo přes DMA kanál využívající buffer v RAM nezávisle na procesoru, jestli od té doby vzniklo něco ještě rychlejšího, tak snad někdo poradí...

Nahlásit jako SPAM
IP: 88.103.236.–
PiranhaGreg0
Stálý člen
24. 4. 2015   #7
-
0
-

Ukážu radši celý program, co zatím mám. Načítám data z velkého binárního souboru, který je řešen jako spoják. Já chci jednotlivé bloky ukládat do samostatných souborů 

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

typedef struct {
	char signature[8];
	uint32_t block_type;
	uint32_t block_size;
	uint32_t next;
} Block;

int main(int argc, char const * argv[]) {
	char name[3 * 9];

	if (argc != 2) {
		fprintf(stderr, "usage: %s <map>", argv[0]);
		return 1;
	}

	FILE * input = fopen(argv[1], "rb");

	while (1) {
		Block b;

		fread(&b, sizeof(b), 1, input);
		b.signature[7] = '\0';

		if (b.block_type == 0x8000)
			break;

		sprintf(name, "%s %04x %04x", b.signature, b.block_type, b.block_size);

		FILE * output = fopen(name, "wb");

		/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
		char * buffer = malloc(b.block_size);

		fread(buffer, 1, b.block_size, input);
		fwrite(buffer, 1, b.block_size, output);

		free(buffer);
		/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */

		fclose(output);
	}

	fclose(input);

	return 0;
}

Kód, který mě zajímá, jestli je takhle optimální je mezi těmi vlnovkami...

Nahlásit jako SPAM
IP: 109.81.210.–
JoDiK
~ Anonymní uživatel
987 příspěvků
24. 4. 2015   #8
-
0
-

#7 PiranhaGreg
Myslím, že je zbytečné ten buffer pokaždé znovu alokovat a uvolňovat, to stačí jednou před cyklem a pak uvolnit až po jeho skončení. Jinak to vypadá v pořádku...

Nahlásit jako SPAM
IP: 88.103.228.–
Zjistit počet nových příspěvků

Přidej příspěvek

Toto téma je starší jak čtvrt roku – přidej svůj příspěvek jen tehdy, máš-li k tématu opravdu co říct!

Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku

×Vložení zdrojáku

×Vložení obrázku

Vložit URL obrázku Vybrat obrázek na disku
Vlož URL adresu obrázku:
Klikni a vyber obrázek z počítače:

×Vložení videa

Aktuálně jsou podporována videa ze serverů YouTube, Vimeo a Dailymotion.
×
 
Podporujeme Gravatara.
Zadej URL adresu Avatara (40 x 40 px) nebo emailovou adresu pro použití Gravatara.
Email nikam neukládáme, po získání Gravatara je zahozen.
-
Pravidla pro psaní příspěvků, používej diakritiku. ENTER pro nový odstavec, SHIFT + ENTER pro nový řádek.
Sledovat nové příspěvky (pouze pro přihlášené)
Sleduj vlákno a v případě přidání nového příspěvku o tom budeš vědět mezi prvními.
Reaguješ na příspěvek:

Uživatelé prohlížející si toto vlákno

Uživatelé on-line: 0 registrovaných, 7 hostů

Moderátoři diskuze

 

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032024 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý