Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » Gepuffertes Lesen aus Datei

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 <
000
03.11.2007, 14:30 Uhr
~Kelloggs
Gast


Grüße!

Ich möchte in C eine Funktion read_buffered schreiben, die genau so wie read() aufgerufen werden kann, allerdings die Daten gepuffet in den als Zeiger übergebenen Speicher schreibt.

Bin langsam dabei, an mir zu Zweifeln. Hat jemand Beispielcode oder kann mir jemand sagen, wie sehr ich mich auf dem Holzweg befinde?


C++:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>


ssize_t read_buffered(int fd, void* destbuff, size_t wantedblock)
{
    static char prebuff[4096]; // der Buffer der Funktion
    static int offset; //Offset zum Zugriff auf den Speicher
    int readbytes = 0;
    int leftbytes = 0;

    ssize_t filereader;

    do
    {
        leftbytes = strlen(prebuff); //schauen wieviel bytes noch im buffer sind

        if(leftbytes == 0) //und ggf. neu einlesen
        {
            filereader = read(fd, prebuff, 4096);
            offset = 0;
        }

        if(wantedblock < leftbytes) // wenn der gewünschte block kleiner als die noch im buffer vorhandenen bytes sind
        {
            memcpy(destbuff, prebuff + offset, wantedblock);
            readbytes = readbytes + wantedblock;
            offset = offset + wantedblock;
            wantedblock = 0;
        }
        else // wenn der vorhandene speicher zu klein oder gleich groß der anfrage ist
        {
            memcpy(destbuff, prebuff + offset, leftbytes);
            readbytes = readbytes + leftbytes;
            wantedblock = wantedblock - leftbytes;
        }
    
    }while(wantedblock != 0 && filereader != 0); // solange der schreibanforderung nicht zurecht gekommen wurde und der filereader noch einen wert zurückgibt

    return readbytes;
}



Danke schon mal im Voraus
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
04.11.2007, 13:18 Uhr
kronos
Quotenfisch
(Operator)



Zitat von ~Kelloggs:
Ich möchte in C eine Funktion read_buffered schreiben, die genau so wie read() aufgerufen werden kann, allerdings die Daten gepuffet in den als Zeiger übergebenen Speicher schreibt.

Macht read nicht genau das? Dann wäre die Lösung z.B.:

C++:
#define read_buffered read


Ansonsten auf den ersten Blick:

C++:
leftbytes = strlen(prebuff); //schauen wieviel bytes noch im buffer sind


Das kann nicht gehen. strlen testet die länge eines strings, also die Anzahl der bytes in prebuff, bis zum ersten byte mit dem Wert 0. Außerdem ist prebuff beim ersten Aufruf noch gar nicht sinnvollen Daten gefüllt... Weiter lese ich erstmal gar nicht.
--
main($)??<-$<='?'>>2?main($-!!putchar(
(("$;99M?GD??(??/x0d??/a:???;a"+'?'/4)
??($??)+'?'/3-2-1+$%2)??''?')):'?';??>
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
04.11.2007, 13:25 Uhr
kronos
Quotenfisch
(Operator)


Okay, mir dämmert was du machen willst
Schau die dazu mal lseek/fseek an...
--
main($)??<-$<='?'>>2?main($-!!putchar(
(("$;99M?GD??(??/x0d??/a:???;a"+'?'/4)
??($??)+'?'/3-2-1+$%2)??''?')):'?';??>
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
04.11.2007, 16:46 Uhr
~Kelloggs
Gast


Hallo Kronos,

read() liest ungepuffert. Wenn, wäre fread() das Mittel der Wahl, aber genau dieses möchte ich praktisch selbst schreiben und an meine Bedürfnisse anpassen.

Habe das Programm nochmal überarbeitet.

Es funktioniert zwischenzeitlich, mit einer Ausnahme: bei einer angeforderten Blockgröße von 1 Byte stimmt. Lässt sich also benutzen wie fread() außer mit 1 Byte Blockgröße


C++:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>


ssize_t read_buffered(int fd, void* destbuff, size_t wantedblock)
{
    static char prebuff[4096]; // der Buffer der Funktion
    static int offset = 0; //Offset zum Zugriff auf den Speicher (bytes gelesen seit read)
    int readbytes = 0; //die in diesem Funktionsaufruf gelesenen bytes
    static int leftbytes = 0; //wieviele bytes noch aus dem prebuff gelesen werden müssen
    static ssize_t filereader;

    do
    {

        if(leftbytes == 0) //und ggf. neu einlesen
        {
            filereader = read(fd, prebuff, 4096);
            offset = 0;
            leftbytes = filereader;
        }

        if(wantedblock <= leftbytes) // wenn der gewünschte block kleiner als die noch im buffer vorhandenen bytes sind
        {
            memcpy(destbuff + readbytes, prebuff + offset, wantedblock);
            readbytes = readbytes + wantedblock;
            offset = offset + wantedblock;
            leftbytes = leftbytes - wantedblock;
            wantedblock = 0;
        }
        else // wenn der vorhandene speicher zu klein oder gleich groß der anfrage ist
        {
            memcpy(destbuff + readbytes, prebuff + offset, leftbytes);
            offset = offset + leftbytes;
            readbytes = readbytes + leftbytes;
            wantedblock = wantedblock - leftbytes;
            leftbytes = 0;
        }
        
    
    }while(wantedblock != 0 && filereader != 0); //solange der schreibanforderung nicht gerecht wurde und der filereader noch einen wert zurückgibt

    return readbytes;
}

 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
04.11.2007, 19:59 Uhr
0xdeadbeef
Gott
(Operator)


Lass das mit den statischen Variablen sein, das fliegt dir spätestens um die Ohren, wenn du mehrere Threads benutzt. Oder wenn du einen zweiten file descriptor auf die Funktion loslässt.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
04.11.2007, 22:16 Uhr
~Kelloggs
Gast


Hmmm. Ohne statische Variablen? Wie geht das? Wenn der Standardpuffer von 4096 größer ist als die angeforderte Blockgröße, muss ich die Daten ja bis zum nächsten Aufruf der Funktion vorhalten. Meines Erachtens ohne static nicht möglich, oder?
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
04.11.2007, 23:51 Uhr
~balduin
Gast



Zitat von ~Kelloggs:
Hmmm. Ohne statische Variablen? Wie geht das? Wenn der Standardpuffer von 4096 größer ist als die angeforderte Blockgröße, muss ich die Daten ja bis zum nächsten Aufruf der Funktion vorhalten. Meines Erachtens ohne static nicht möglich, oder?

Heapspeicher mittels malloc() reservieren und benutzen, geht doch auch!
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
007
04.11.2007, 23:56 Uhr
0xdeadbeef
Gott
(Operator)


Ich dachte eigentlich mehr daran, die Puffer als Parameter respektive in einem struct zu übergeben. Halt wie fread das macht - auf diese Art jedenfalls kommst du nicht besonders weit.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 <     [ C / C++ (ANSI-Standard) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: