Đọc và ghi tập tin bằng C# – read and write file with C# .net

read and write

Việc đọc và ghi ra một tập tin là việc làm cần thiết trong trường hợp chúng ta muôn in ra kết quả chương trình ra một file, lấy nối dung từ một file để sử dụng trong chương trình của mình… Trong môi trường .net với ngôn ngữ C# nói riêng và các ngôn ngữ khác nói chung, việc thực hiện tương đối dễ dàng với sự hỗ trợ đắc lực của lớp trình bày nội dung gọi chung là stream. Bài viết này sẽ có trình bày ngắn gọn việc đọc và ghi file trong C# dựa trên các lớp sẵn có của .NET, với mỗi trường hợp sẽ có chương trình Demo cụ thể viết trên Visual studio 2010.

1. Giới thiệu về Stream

–  Đọc và viết dữ liệu sẽ được thực hiện thông qua lớp stream. Stream là dòng dữ liệu chảy đi. Đây là một thực thể (entity) có khả năng nhận được hoặc tạo ra một “nhúm” dữ liệu. System.IO.Stream là một lớp  abstract định nghĩa một số thành viên chịu hỗ trợ việc đọc/viết đồng bộ (synchronus) hoặc không đồng bộ (asynchronous) đối với khối trữ tin (nghĩa là một tập tin trên đĩa hoặc tập tin trên ký ức).

–  Vì Stream là một lớp abstract, nên bạn chỉ có thể làm việc với những lớp được dẫn  xuất từ Stream. Các hậu duệ của Stream tượng trưng dữ liệu như là một dòng dữ liệu thô dạng bytes (thay vì dữ liệu dạng văn bản). Ngoài ra, các lớp được dẫn xuất từ Stream hỗ trợ việc truy tìm (seek) nghĩa là một tiến trình nhận lấy và điều chỉnh vị trí trên một dòng chảy. Trước khi tìm hiểu những chức năng mà lớp Stream cung cấp, bạn nên xem qua các thành viên của lớp Stream.

–  Ý tưởng của stream đã có từ lâu. Một stream là một đối tượng dùng để chuyển dữ liệu. Dữ liệu có thể được truyền theo hai hướng:

  • Nếu dữ liệu được truyền từ nguồn bên ngoài vào trong chương trình của bạn, ta gọi là đọc dữ liệu
  • Nếu dữ liệu được truyền từ chương trình của bạn ra nguồn bên ngoài , ta gọi là viết dữ liệu

–  Thường thì nguồn bên ngoài sẽ là một file, ngoài ra nó còn bao gồm cả trường hợp sau:

  • Đọc hoặc ghi dữ liệu trên mạng dùng giao thức mạng
  • Đọc hoặc ghi đến một đường ống chỉ định
  • Đọc hoặc ghi đến một vùng của bộ nhớ

–  Các lớp có mối liên hệ trong namespace System.IO như hình sau:

image

2.  Làm việc với file nhị phân (binary files)

Reading and writing to binary files thường được làm việc với lớp FileStream .

a. Làm việc với FileStream

–  Lớp FileStream đem lại việc thi công cho những thành viên của lớp abstract Stream theo một thể thức thích hợp đối với các file-base streaming giống như các lớp DirectoryInfo và FileInfo, lớp FileStream cho phép mở những tập tin hiện hữu cũng như tạo mới file. Khi tạo tập tin , lớp FileStream  thường dùng những enum FileMode, FileAccess và FileShare.

// tạo một tập tin mới trên thư mục làm việc FileStream myFStream = new FileStream("test.dat", FileMode.OpenOrCreate, FileAccess.ReadWrite);

b. The FileStream Class:

FileStream được sử dụng đọc và viết dữ liệu vào hoặc từ một file. Để khởi tạo một FileStream, bạn cần 4 phần sau:

  • file bạn muốn truy xuất .
  • mode, cho biết bạn muốn mở file như thế nào.
  • access, cho biết bạn muốn truy xuất file như thế nào – bạn định đọc hoặc viết file hoặc cả hai.
  • share access – khả năng truy xuất file.
Enumeration Values
FileMode Append, Create, CreateNew, Open, OpenOrCreate, or Truncate
FileAcess Read, ReadWrite, or Write.
FileShare Inheritable, None, Read, ReadWrite, or Write.

3. Làm việc với BufferedStream

–  Khi bạn gọi hàm Read() thì một công tác đọc dữ liệu cho đầy buffer từ đĩa được tiến hành. Tuy nhiên, để cho có hiệu năng, hệ điều hành thường phải đọc trong một lúc một khối lượng lớn dữ liệu tạm thời trữ trên bufer. Buffer hoạt động như một kho hàng.

–  Một đối tượng Bufered stream cho phép hệ điều hành tạo buffer riêng cho mình dùng, rồi đọc dữ liệu vào hoặc viết dữ liệu lên ổ đĩa theo một khối lượng dữ liệu nào đó mà hệ điều hành thấy là có hiệu năng. Tuy nhiên, bạn xũng có thể ấn định chiều dài khối dữ liệu. Nhưng bạn nhớ cho là buffer sẽ chiêmd chỗ trong ký ức chứ không phải trên đĩa từ. Hiệu quả sử dụng đến buffer là ciệc xuất nhập dữ liệu chạy nhanh hơn.

–  Một đối tượng BufferedStream được hình thành xung quanh một đối tượng Stream mà bạn đã tạo ra trước đó. Muốn sử dụng đến một BufferedStream bạn bắt đầu tạo một đối tượng Stream thông thường như trong ví dụ:

stream inputstream = File.OpenRead(@"C;\test\source\folder3.cs ");

stream outputstream = File.Openwrite(@"C:test\source\folder3.bak");

–  Một khi bạn đã có stream bình thường, bạn trao đối tượng này cho hàm constructor của buffere stream:

BufferedStream bufInput = new BufferedStream(inputstream);

BufferedStream bufOutput = new BufferedStream(outputstream);

–  Sau đó, bạn sử dụng BufferedStream như là một stream bình thường, bạn triệu gọi hàm Read() hoặc Write() như bạn đã làm trước kia. Hệ điều hành lo việc quản lý vùng đêm:

while ((bytesRead = bufInput.Read(buffer, 0, SIZE_BUFF)) > 0)
{
    bufOutput.Write(buffer, 0, bytesRead);

}

–  Chỉ có một khác biệt mà bạn phải nhớ cho là phải tuôn ghi (flush) nội dung của buffer khi bạn muốn bảo đảm là dữ liệu được ghi lên đĩa.

bufOutput.Flush();

–  Lệnh trên bảo hệ điều hành lấy toàn bộ dữ liệu trên buffer cho tuôn ra ghi lên tập tin trên đĩa.

4.  Làm việc với những tập tin văn bản

–  Nếu bạn biết file bạn đang làm việc (đọc/viết) thuộc loại văn bản nghĩa là dữ liệu kiểu string, thì bạn nên nghĩ đến việc sử dụng đến các lớp StreamReader và StreamWriter. Cả hai lớp theo mặc nhiên làm việc với ký tự Unicode. Tuy nhiên bạn có thể thay đổi điều này bằng cách cung cấp một đối tượng quy chiếu được cấu hình một cách thích hợp theo System.Text.Reference. Nói tóm lại hai lớp này được thiết kế để thao tác dễ dàng các tập tin loại văn bản.

–  Lớp StreamReader được dẫn xuất từ một lớp abstract mang tên TextReader cũng giống như String Reader. Lớp cơ bản TextReader cung cấp một số chức năng hạn chế cho mỗi hậu duệ, đặc biệt khả năng đọc và “liếc nhìn” (peek) lên một dòng ký tự (character stream).

–  Lớp StreamWriter và StringWriter cũng được dẫn xuất từ một lớp abstract mang tên TextWriter; lớp này định nghĩa những thành viên cho phép các lớp dẫn xuât viết những dữ liệu văn bản lên một dòng văn bản nào đó.

–  Các hàm thành viên của lớp TextWriter

Close() Cho đóng lại các writer và giải phóng mọi nguồn lực chiếm dụng
Flush() Cho xoá sạch tất cả các buffer đối với writer hiện hành
NewLine Thuộc tính này dùng làm hằng sang hằng
Write() Viết một hằng lên text stream không có newline constant
WriteLine() Viết một hằng lên text stream có newline constant

Ví dụ đọc, viết một tập tin văn bản:

–  Ví dụ ReadWriteText trình bày cách sử dụng của lớp StreamReader và StreamWriter. Nó trình bày file được đọc vào và hiển thị Nó cũng có thể lưu file. Nó sẽ lưu bất kỳ file ở định dạng Unicode .

–  Màn hình trình bày ReadWriteText được dùng hiển thị ở chương trình demo. Chúng ta có thể đọc được ở nhiều định dạng file khác.

–  Chúng ta nhìn vào đoạn mã sau. Trước tiên ta thêm câu lệnh using , Từ đây bên cạnh System.IO, chúng ta sử dụng  lớp StringBuilder từ System.Text namespace để xây dựng chuỗi trong textbox:

using System.Text;
using System.IO;

–  Tiếp theo chúng ta thêm các trường cho lớp main form:

public partial class Form1 : Form {
     private OpenFileDialog FileOpen = new OpenFileDialog();
     private string chooseFile;

–  Chúng ta cũng cần thêm vài chuẩn mã Windows Forms để thực hiện điều khiển cho menu và hộp thoại:

public Form1()
{
    InitializeComponent();
    this.MaximizeBox = false;
    this.StartPosition = FormStartPosition.CenterScreen;
    FileOpen.FileOk += new CancelEventHandler(FileOpen_FileOk);
}

private void openToolStripMenuItem_Click(object sender, EventArgs e)
{
    FileOpen.ShowDialog();
}
void FileOpen_FileOk(object sender, CancelEventArgs e)
{
    chooseFile = FileOpen.FileName;
    this.Text = Path.GetFileName(chooseFile);
    DisplayFile();
}

–  Từ đây chúng ta thấy mỗi khi người sử dụng nhấn OK để chọn một file trong hộp thoại, chúng ta gọi phương thức DisplayFile(), dùng để đọc file.

private void DisplayFile()
{
    int nCols = 16;
    FileStream inStream = new FileStream(chooseFile, FileMode.Open,
                                                     FileAccess.Read);
    long nBytesToRead = inStream.Length;
    if (nBytesToRead > 65536 / 4)
        nBytesToRead = 65536 / 4;
    int nLines = (int)(nBytesToRead / nCols) + 1;
    string[] lines = new string[nLines];
    int nBytesRead = 0;
    for (int i = 0; i < nLines; i++)
    {
        StringBuilder nextLine = new StringBuilder();
        nextLine.Capacity = 4 * nCols;
        for (int j = 0; j < nCols; j++)
        {
            int nextByte = inStream.ReadByte();
            nBytesRead++;
            if (nextByte < 0 || nBytesRead > 65536)
                break;
            char nextChar = (char)nextByte;
            if (nextChar < 16)
                nextLine.Append(" x0" + string.Format("{0,1:X}",
                                                     (int)nextChar));
            else if (char.IsLetterOrDigit(nextChar) ||
                                     char.IsPunctuation(nextChar))
                nextLine.Append(" " + nextChar + " ");
            else nextLine.Append(" x" + string.Format("{0,2:X}",
                                       (int)nextChar));
        }
        lines[i] = nextLine.ToString();
    }

    inStream.Close();
    richTextBox.Lines = lines;

}

–  Như vậy chúng ta đã mở được file  nhờ phương thức DisplayFile(). bây giờ chúng ta xử lý cách để lưu file chúng ta thêm đoạn mã SaveFile(). Bạn nhìn vào phương thức SaveFile() chúng ta viết mỗi dòng ra textbox, bằng  stream StreamWriter

void SaveFile()
{
    StreamWriter sw = new StreamWriter(chooseFile, false,
                          Encoding.Unicode);
    foreach (string line in richTextBox.Lines)
        sw.WriteLine(line);
    sw.Close();
}

–  Bây giờ ta xem xét làm thế nào file được đọc vào. Trong quá trình xử lý thực sự chúng ta không biết có bao nhiêu dòng sẽ được chứa. Chúng ta giải quyết vấn đề này bằng cách ban đầu đọc file vào trong lớp đại diện StringCollection, được nằm trong System.Collections.Specialized namespace. Lớp này được thiết kế để giữ một bộ của chuỗi có thể được mở rộng một cách linh hoạt. Nó thực thi hai phương thức : Add(), nó thêm một chuỗi vào bộ chọn lựa (collection) , và CopyTo(), nó sao chép string collection vào trong một mảng. Mỗi thành phần của đối tượng StringCollection object sẽ giữ 1 hàng của file.

–  Bây giờ chúng ta sẽ xem xét phương thức ReadFileIntoStringCollection() . Chúng ta sử dụng StreamReader để đọc trong mỗi hàng. Khó khăn chính là cần đếm ký tự đọc để chắc chúng ta không vượt quá khả năng chứa đựng của textbox:

private StringCollection ReadFileIntoStringCollection()
{
    const int MaxBytes = 65536;
    StreamReader sr = new StreamReader(chooseFile);
    StringCollection result = new StringCollection();
    int nBytesRead = 0;
    string nextLine;
    while ((nextLine = sr.ReadLine()) != null)
    {
        nBytesRead += nextLine.Length;
        if (nBytesRead > MaxBytes)
            break;
        result.Add(nextLine);
    }
    sr.Close();
    return result;
}

–  Đến đây đoạn mã được hoàn thành.

Click vào đầy để download chương trình demo đọc và ghi tập tin ra file txt viết trên visual studio 2010

(Tham khảo Kỹ thuật Lập trình C# 2.0)

Advertisements

About thanhcuong1990

Handsome and talent!! ^^
This entry was posted in C#. Bookmark the permalink.

38 Responses to Đọc và ghi tập tin bằng C# – read and write file with C# .net

  1. Nguyễn Văn Dũng says:

    Chào bạn, mình có 1 file, mình cũng chưa biết đọc và viết nó ra như thế nào. bạn có thể giúp mình được ko. Nếu được thì bạn cho mình mail của bạn, mình gửi qua mail nhờ bạn xem hộ mình, cảm ơn bạn nhiều, mail của mình là: vandungevn@gmail.com.

  2. Quang Sơn says:

    Chào bạn mình muốn đọc file PDF thi sao ah???
    sonnq.sp@gmail.com

  3. tronghuukhtn says:

    cho mình hỏi, vậy mình có thể đọc file nhạc thì sao bạn?

  4. Hoàng Kỳ Sơn says:

    Anh Cường ơi cho em hỏi là muốn đọc file word thì thế nào ạ?

  5. Quoc says:

    Chào bạn, mình muốn đọc 1 file txt sau đó đưa dữ liệu vào trong các lable
    vd: file txt là giá của từng sản phẩm, và mỗi lable
    bạn có thể giup mình không

    • Trường hợp của bạn là đọc hết nội dung file text rồi cắt từng dòng về tên sản phẩm và giá của sản phẩm sau đó gán text của lable thành từng dòng vừa đọc được từ file text là ok.

  6. Lanh says:

    anh cuong oi cho e hoi nhe?
    E muon doc file *.cuongcung thi lam the nao?

  7. TOMD says:

    Em muốn đoc file DAT thì như thế nào hả a

    • Đọc file DAT cũng tương tự thôi bạn. Thực chất nều file .DAT lưu dưới dạng text thì cũng như đổi đuôi file .txt thành đuôi .DAT.

  8. TOMD says:

    EM muốn đọc va ghi video thi làm thế nào a ơi.Chỉ cho e vs..

  9. thuc says:

    em chào anh!
    anh cho em hỏi bây h em muốn đọc một file ảnh (.jpg), sau đó truyền qua uart, thì phải làm thế nào ạ. em cám ơn anh

    • Thực sự mình cũng chưa biết từ “uart” (Universal asynchronous receiver/transmitter) mà bạn viết là gì? Nghe giống như lập trình cho robot vậy. 🙂

  10. Tuan says:

    Demo của bạn sử dụng làm sao vậy?
    Tạo file mình ko nhập đc tên file ah bạn?
    richTexBox đó để nhập nội dung file ah bạn?

  11. hoa trang says:

    hi, Mr Cuong!
    Em muốn ghi một file .jpg vào thẻ SD thì phải làm như thế nào ạ? (em dung Pic18). Anh giúp em với. Thank you very much!

  12. vietha says:

    thanks các bạn nha.mình đang rất cần mấy cái này.à tiện cho mình hỏi nếu mình muốn thay đổi vị trí của các từ trong file txt đó thì làm ntn dc không

  13. Đạt says:

    anh cường ơi cho em hỏi là cái bộ đệm có phải là 1 phần trong stream ko?bộ đệm != stream phải ko anh?em đang học đọc file trong C.dữ liệu mình đọc vào nó vào stream nhập chuẩn trước hay vào bộ đệm bàn phím trước hả anh???

  14. haiuyen says:

    anh ơi em muốn mỗi giây chỉ hiện 1 dòng trong file text lên textbox thì làm thế nào ạ?

  15. Nghĩa says:

    Chào anh, em đang làm đề tài về c#, nếu muốn đọc file 3d thì phải làm sao anh, e chưa có hướng suy nghĩ nào cả.

  16. tân says:

    Chào anh, anh cho em hỏi việc mình đọc( ghi )cả 1 khối dữ liệu vào thì có gì khác không a, và thực hiện như thế nào ạ

  17. chào anh e muốn đọc 1 file ảnh(.bmp ) thì lam như nào ạ?

  18. khánh says:

    chào anh, em có 1 file text và muốn import vào file excel thì làm sao ạ (file text gồm 2 cột gồm số báo danh và điểm)
    vd của file text:
    A12 9.5
    yêu cầu đặt ra là nạp dữ liệu ctuwf flie text đó vào file excel số báo danh một ô và điểm một ô, 2 ô cùng trên một hàng
    em cám ơn 🙂

  19. Lương hải says:

    anh có thể chỉ cho em cách ghi thêm dữ liệu vào một file excel đã có sẵn sau đó save lại chứ không save as không. Vì save as nó sẽ hỏi có ghi đè không mà ghi đè là bị mất dữ liệu trước đó trong file excel.

  20. Thủy Trân says:

    anh ơi cho em hỏi là khi em muốn đọc file tới 1 ký tự nào đó rồi dừng thì phải làm sao ạ?
    Ví dụ: file có nội dung là: Nguyen Van A – 300796 (cùng nằm trên 1 dòng)
    Em muốn đọc tới Nguyen Van A thôi, bỏ dấu ‘-‘ đi và đọc tiếp ‘3007’
    Em cám ơn anh!

    • Trường hợp này bạn đọc từng character trong file text của bạn. Cứ mỗi character bạn so sánh nó có phải là dấu ‘-‘ hay không. Nếu là dấu trừ thì bỏ qua ký tự đó không append vào chuỗi.

  21. nguyễn Thắng says:

    hi chào bạn. bạn cho mình hỏi. mình muốn lấy dữ liệu file dxf ( File autocad ) thì làm thế nào nhỉ
    mình thử mấy thư viện mà đưa vào chẳng hiểu dùng thế nào vì không có tài liệu
    type mình muốn lấy dữ liệu là dạng spline trong file dxf.

  22. Binh Duong says:

    Hi, chào anh em muốn lấy dữ liệu từ một máy khác trong mạng LAN thì ntn nhỉ. em cảm ơn !

  23. Chào anh, em muốn Write lại file cũ nhưng ghi đè lên or xóa dữ liệu trong file cũ xong add lại thì phải làm sao ah?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s