其他分享
首页 > 其他分享> > 在C中使用直接访问文件

在C中使用直接访问文件

作者:互联网

我对C非常陌生(实际上是对程序进行一般编程),并且正在从事一个令我感到困惑的项目(不难做哈).该项目涉及直接访问文件.我们将创建一个由一系列零件记录组成的文件.以下是一些规格:

Should contain a header record (24 bytes – filled) indicating the
number of valid items.

Each (24 byte-long) data record will contain a
stock number (4 digits max), a description (8 characters max), a count
(4 digits), and a “test part” indicator( 4 digits max => -1 – end of
file).

This file will initially hold 20 blank (dummy) records and will
be created sequentially.

Once the file has been created, an update
sequential text file will be accessed based on stock numbers and new
records will be inserted into the file.

When the update is complete,
the valid parts records will be printed in order starting at stock
record “1”.

Update by reading the text update file (prog4.dat) and
seeking the file position based on the stock number (don’t forget the
header record)

例如:

Initial (empty)
Input (updates)
    1 widgits 25 3
    6 gidgits 12 8
    8 kidgits 6 -1
    3 didgits 11 6
Output
    1 widgits 25
    3 didgits 11
    6 gidgits 12
    8 kidgits 6

我对Direct Access文件一无所知,因此一直在查看我在Google上找到的几个不同链接(特别是http://cee-ux49.cee.illinois.edu/cee490/public_html/pdfs_vgs/aL23_Direct_Access_Files.pdfhttp://www.learncpp.com/cpp-tutorial/137-random-file-io/),但是在弄清楚如何使此特定程序正常工作方面遇到了麻烦.

就像我说的那样,我没有做太多的代码处理,这让我感到很困惑,而我所做的主要是基于第一个链接,所以我不知道这是正确的(不确定给出的大小)向量,因为我不确定我的特定问题(也许是零件的阵列?)会是什么,但是这里是我所能想到的.

#include <iostream>
#include <string>
#include <fstream>
#include <stream>
using namespace std;

class records {
public:
        int getStckNumber() {
                return stockNumber;
        }
        void setStockNumber(int stockNum) {
                stockNumber = stockNum;
        }

        string getItemDespcription() {
                return itemDescription;
        }
        void setItemDespcription(string itemDescrip) {
                itemDescription = itemDescrip;
        }

        int getItemAmount() {
                return itemAmount;
        }
        void setItemAmount(int itemAmt) {
                 itemAmount = itemAmt;
        }

        int getNext() {
                return next;
        }
        void setNext(int nxt) {
                next = nxt;
        }
private:
        int stockNumber;
        string itemDescription;
        int itemAmount;
        int next;
        int recNum;
}


int main() {
        int stockNumber;
        string itemDescription;
        int itemAmount;
        int next;
        int recNum;
        int recSize = sizeof(int) + sizeof(string) + sizeof(int) + sizeof(int) + sizeof(int);

        istream updateFile;
        updateFile.open("prog4.dat");
        if(!updateFile) {
                cerr << "Open Failure" << endl;
                exit(1);
        }
}

这是我将用于更新的文件:

10 zidgits 17 -1
14 lidgits 2 7
6 gidgits 12 8
1 bidgits 25 3
16 widgits 9 10
7 midgits 0 2
3 didgits 11 6
5 tidgits 5 16
2 pidgits 7 5
8 kidgits 6 14

这是我的一些具体问题:

>如何将信息从updateFile存储到要写入输出文件的变量中(尚未创建)?
>如何获取以正确顺序写入数据的数据,因为它基于updateFile每行的最后一个数字.

例如,假定输出文件以最低的stockNumber为1开始,因此基于该文件,具有stockNumber 1的项目为bidgits.然后,该文件应该查看该行(3)上的最后一个数字,并使用该stockNumber(didgits)写入该项目的信息,依此类推.

这些是目前我突然想到的主要问题,但是我相信随着这一过程的进行,还会弹出更多问题.任何帮助将不胜感激.另外,这大约需要5个小时,因此,我将尽可能地坚持现有的代码(我当然会添加更多代码).

解决方法:

对于这样的项目,我想要编写一些原始函数来读取和写入整个记录以及更新文件头.

我将创建POD类型的结构来存储要从数据文件读取或写入数据文件的单个记录.

例如:

struct header
{
    uint32_t valid; // number of valid records
    char pad[20]; // padding to make this object 24 bytes
};

struct record
{
    char no[4]; // stock number
    char desc[8]; // description
    uint32_t count;
    uint32_t test_part;
    char pad[4];  // padding to make this object 24 bytes
};

写入标头的功能(始终位于文件位置0):

std::iostream& write(std::iostream& ios, const header& h)
{
    ios.clear(); // clear any errors
    ios.seekg(0); // move to beginning of file
    ios.write(reinterpret_cast<const char*>(&h), sizeof(h)); // write the header to file
    return ios; // return the stream (for easy error detection/chaining)
}

在特定位置写入记录也是一样:

std::iostream& write(std::iostream& ios, const record& r, size_t pos)
{
    ios.clear(); // clear any errors
    ios.seekg(sizeof(header) + (sizeof(record) * pos)); // move to record's position
    ios.write(reinterpret_cast<const char*>(&r), sizeof(r)); // write the record to file
    return ios; // return the stream (for easy error detection/chaining)
}

然后,您可以根据这些原语编写初始化函数:

std::iostream& init(std::iostream& ios, size_t num)
{
    // Update the header to zero records
    header h;
    h.valid = 0;
    write(ios, h);

    // create each record with a -1 (EOF) marker
    record r;
    r.test_part = uint32_t(-1);

    // output 20 copies of that record.
    for(size_t pos = 0; pos < num; ++pos)
        write(ios, r, pos);

    return ios;
}

然后在真实文件上调用所有这些,如下所示:

int main()
{
    assert(sizeof(header) == 24);
    assert(sizeof(record) == 24);

    // binary mode io!
    std::fstream fs("records.dat", std::ios::in|std::ios::out|std::ios::binary);

    if(!init(fs, 20))
    {
        std::cerr << "ERROR: initializing data file:" << std::endl;
        return 1;
    }

    // ...
}

注意:此代码是匆忙编写的,未经完全测试,仅作为解决此问题的示例.希望它会给您一些想法.

还:在系统之间,甚至在同一平台上的同一编译器的不同版本之间,这样写入二进制文件不是很容易移植.

标签:random-access,c,file
来源: https://codeday.me/bug/20191010/1883589.html