Προς το περιεχόμενο

C Εγγραφή σε αρχείο bit προς bit


bnvdarklord

Προτεινόμενες αναρτήσεις

Δημοσ.

Καλησπέρα,

 

Θέλω να γράψω σε κάποιο αρχείο δεδομένα bit προς bit. Ψαχνοντας λίγο στο google απο οτι κατάλαβα θα πρεπει να έχω εναν buffer μεγεθους 1byte τουλαχιστον και μολις γεμίζει να τον γράφω στο αρχείο που θέλω... Αυτός είναι ο σωστός τρόπος ή γινεται και αλλιώς;

 

Αν πρέπει να γίνει έτσι παντως εχω κολλήσει στο πως θα δηλωσω εναν τετοιο buffer, καθώς και το πως θα του περναω μεσα ένα ένα τα bit...

Δημοσ.

Αρκεί να συνδιάσεις τα δύο πρώτα listings από τα sites...

http://www.cplusplus.com/reference/clibrary/cstdio/fread/

 

http://www.cplusplus.com/reference/clibrary/cstdio/fwrite/

 

Γενικά, δεν διαβάζεις πότε bit-bit, πάντα byte-byte.

 

δηλώνεις έναν buffer σχετικά μεγάλο

ας πούμε 1024bytes τον γεμίζεις διαβάζοντας από το ένα αρχείο και τον αδειάζεις γράφοντας στο άλλο.

Δημοσ.

Σ'ευχαριστώ...

 

Το θεμα είναι οτι δεν διαβάζω από αρχείο ακριβως, θελω να γραφω καθε φορα καποια bit + τα bit απο εναν χαρακτήρα ascii(λογω κωδικοποιησης σε lz78 που προσπαθώ να φτιάξω)...

Οποτε αφου δημιουργήσω αυτόν τον buffer πως του περνάω μέσα τα 8 bit ενός ascii χαρακτήρα ή τα 3bit ενός 3bitου αριθμού;

Δημοσ.

Νομίζω μπορείς να το κάνεις με shifts <<, >>

Γενικά πρέπει να ψάξεις για bit operations

Δημοσ.

Μμμ ναι κατι τετοιο σκεφτηκα... Αν θελω να περάσω κατι μεγέθους n bit κανω τον buffer ολισθηση κατα n bit και μετα xor με το ''κατι''...

Σας ευχαριστώ θα το ψαξω και λιγο περισσοτερο.

Δημοσ.

φυσικά bit ολίσθηση μπορείς να κάνεις στους ακέραιους τύπους (όχι σε ολόκληρη τη buffer)

 

μια πρόταση για αλλαγή ενός bit σε κάποια buffer

>
void set(unsigned char *x,size_t pos,bool flag){
   const size_t N = CHAR_BITS; //limits.h
   if(flag)
             x[pos / N] |= (1 << (pos % N));
             //ή x[pos >> 3] |= (1 << (pos&7)) για τους γνώστες
             //για να χρησιμοποιηθεί το N αντί για 3 και 7 στην παραπάνω γραμμή, απαιτούντε log()
   else
             x[pos / N] &= (~(1 << (pos % N)));
}

ανάλογα υλοποιείς και το get

 

για περισσότερα bit απο ένα, ο παραπάνω κώδικας σηκώνει περισσότερη βελτιστοποίηση...

Δημοσ.

Δοκίμασα με επιτυχία το εξής

 

>
#include <cstdio>

int main()
{
char buffer = 0;

int a = 2; // 10;		
buffer = buffer ^ a; // xor

int b = 5; // 101
buffer = buffer << 3; 
buffer = buffer ^ b; // buffer should be 00010101

FILE *in = fopen("mybuff", "wb");
fwrite(&buffer, 1, sizeof(buffer), in);
fclose(in);	

return 0;
}

 

 

Με buffer 1byte το αρχείο οντως περιέχει αυτό που πρέπει. Δοκίμασα με μεγαλύτερο buffer (char buffer[2] πχ) αλλα δεν γινεται comile γιατι ετσι δεν δουλευουν το xor και η ολίσθηση.... :-(

 

edit: μηπως μπορείς να εξηγίσεις τον κώδικα που πόσταρες :P

Δημοσ.

το x[pos / N] είναι το byte που περιέχει το bit pos.

(το x[0] περιέχει τα bit 0 έως 7, το x[1] τα 8 εώς 15,...,το x[pos /N] τα pos έως pos+7)

 

το (pos % N) είναι αριθμός στο διάστημα [0,7] και είναι ο αριθμός του bit στο παραπάνω byte.

 

Χρησιμοποιώ τον πίνακα unsigned char x[1024] σαν ένα πίνακα δυο διαστάσεων απο bit με διαστάσεις [8][1024],

το pos /N δείχνει τη γραμμή του πίνακα και το pos %N τη στήλη [0,7].

 

Αν θέλουμε να κάνουμε το bit εκείνο 1, κάνουμε OR με το 1 << (pos%N), αλλιώς κάνουμε AND με το αντίστροφο του.

Δημοσ.

Θα σου πρότεινα να χρησιμοποιήσεις buffer 4ΚΒ τουλάχιστον, όσο είναι και το block του NTFS, ώστε να έχεις ικανοποιητική ταχύτητα.

Δημοσ.
Μμμ μου βγαζει error στο CHAR_BITS και εχω βαλει το climits...

Αυτο που προσπαθησα παραπάνω ειναι λαθος;

είναι CHAR_BIT (το S περισσεύει:shifty:) και ουσιαστικά είναι η σταθερά 8.

 

Αυτό που έκανες μπορεί να λειτουργήσει σε επίπεδο char ή ακεραίου, αλλά μην χρησιμοποιείς το XOR για να κάνεις το bit 1, αλλά το OR.

 

π.χ. εστω buffer = 00001000 και mask = 00001000 (γι'αυτο δεν προτιμάμε το XOR για τέτοια δουλειά)

buffer ^= mask θα σου δωσει 0,

ενώ buffer |= mask θα αφήσει 00001000 (σωστά) το buffer

Αν είσαι σίγουρος ότι τα bit που θέλεις να κάνεις 1 στο buffer, είναι σίγουρα μηδενικά, τότε και μόνο τότ λειτυργει σωστά και το XOR

Δημοσ.

Γίνεται να τροποποιήσω αυτό που έκανα ώστε να έχω μεγαλύτερο buffer?

Αυτό που εφτιαξες εσύ δεν το εχω πολυκαταλάβει ακόμα πως λειτουργεί ...

 

edit : Τωρα προσπαθω να εχω 2 buffer έναν 1byte και 1 2byte, και οταν γεμίζει ο μικρός να περνάω τα δεδομένα του στον μεγάλο...

 

edit2: Μια πρώτη προσπάθεια στην οποία ο μικρός buffer υποθέτω οτι γεμίζει παντα ακριβώς:

 

 

>
#include <cstdio>
#define SIZE 5

char buffer[size] = {0};
int index = 0;
int fill = 0;


void set(char *b, int data, int size)
{
fill = fill + size;

*b = *b << size;
*b = *b ^ data;	

if(fill == 8)
{
	fill = 0;
	buffer[index] = *b;
	index++;
	*b = 0;
}

}

void check(FILE *in)
{
if(index > SIZE)
{
	fwrite(buffer, 1, sizeof(buffer), in);
	index = 0;
}	
}

int main()
{
char b = 0;

FILE *in = fopen("mybuff", "wb");

for(int i = 0; i < 15; i++)
{	
	set(&b, 10, 4); // add 10 in b
	check(in); // is buffer full? 
	set(&b, 15, 4);
	check(in);
}

if(index < SIZE) // leftovers
	fwrite(buffer, 1, index*sizeof(char), in);

fclose(in);	

return 0;
}

 

 

 

Ανησυχώ μηπως αυτό είναι καπως αργό...

Δημοσ.

όταν γράφεις τα δεδομένα στο αρχείο, δεν μηδενίζεις τον πίνακα...

αυτό σε συνδιασμό με το XOR που δεν λες να αλλάξεις είναι bug.

 

Απο ταχύτητα δεν βλέπω κάποιο σοβαρό πρόβλημα (εκτός απο το μικρό μέγεθος της buffer).

Δημοσ.

Τον πίνακα δεν τον μηδενίζω για τον εξής λόγο:

Μηδενίζοντας το index οτι νεο γραφω κανει overwrite τα παλιά και τα σκουπίδια που μενουν απο πριν δεν γραφονται στο αρχείο εφόσον οτι περισσευει το γραφω στο αρχείο με μεγεθος index*sizeof(char)...

Το xor το αφησα επειδη κανω ολισθηση τον buffer για να προσθεσω τα επομενα bits...

Αρχειοθετημένο

Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.

  • Δημιουργία νέου...