Làm cách nào để ghi byte vào một tệp trong python?

Trong hướng dẫn nhanh này, chúng ta sẽ tìm hiểu một số cách khác nhau để ghi một mảng byte Java vào một tệp. Chúng ta sẽ bắt đầu từ đầu, sử dụng gói Java IO. Tiếp theo, chúng ta sẽ xem xét một ví dụ sử dụng Java NIO. Sau đó, chúng tôi sẽ sử dụng Google Guava và Apache Commons IO

2. IO Java

Gói Java IO đã có từ JDK 1. 0 và cung cấp một tập hợp các lớp và giao diện để đọc và ghi dữ liệu

Hãy sử dụng FileOutputStream để ghi hình ảnh vào một tệp

File outputFile = tempFolder.newFile["outputFile.jpg"];
try [FileOutputStream outputStream = new FileOutputStream[outputFile]] {
    outputStream.write[dataForWriting];
}

Chúng tôi mở một luồng đầu ra tới tệp đích của mình và sau đó chúng tôi có thể chỉ cần chuyển dữ liệu byte[] dataForWriting của mình cho phương thức ghi. Lưu ý rằng chúng tôi đang sử dụng khối tài nguyên dùng thử ở đây để đảm bảo rằng chúng tôi đóng OutputStream trong trường hợp IOException bị ném

3. Java NIO

Gói Java NIO được giới thiệu trong Java 1. 4 và API hệ thống tệp cho NIO đã được giới thiệu dưới dạng tiện ích mở rộng trong Java 7. Java NIO đang sử dụng bộ đệm và không chặn, trong khi Java IO sử dụng luồng chặn. Cú pháp tạo tài nguyên tệp ngắn gọn hơn trong java. niô. gói tập tin

Chúng ta có thể viết byte[] của mình trong một dòng bằng lớp Tệp

Files.write[outputFile.toPath[], dataForWriting];

Ví dụ của chúng tôi tạo tệp hoặc cắt bớt tệp hiện có và mở tệp để ghi. Chúng ta cũng có thể sử dụng Đường dẫn. get[“đường dẫn/đến/tệp”] hoặc Đường dẫn. get[“path”, “to”, “file”] để xây dựng Đường dẫn mô tả nơi tệp của chúng ta sẽ được lưu trữ. Đường dẫn là cách thể hiện đường dẫn riêng của Java NIO

Nếu cần ghi đè hành vi mở tệp, chúng tôi cũng có thể cung cấp OpenOption cho phương thức ghi

4. Ổi Google

Ổi là một thư viện của Google cung cấp nhiều loại để thực hiện các hoạt động phổ biến trong Java, bao gồm cả IO

Hãy nhập Ổi vào pom của chúng ta. tập tin xml


    com.google.guava
    guava
    31.0.1-jre

4. 1. Tệp ổi

Như với gói Java NIO, chúng ta có thể viết byte[] trong một dòng

Files.write[dataForWriting, outputFile];

Tập tin của ổi. phương thức ghi cũng có một Tùy chọn Tùy chọn tùy chọn và sử dụng các giá trị mặc định giống như java. niô. Các tập tin. viết

Có một nhược điểm ở đây. Các tập tin ổi. phương thức ghi được đánh dấu bằng chú thích @Beta. , điều đó có nghĩa là nó có thể thay đổi bất cứ lúc nào và do đó không được khuyến nghị sử dụng trong thư viện

Vì vậy, nếu chúng ta đang viết một dự án thư viện, chúng ta nên cân nhắc sử dụng ByteSink

4. 2. ByteSink

Chúng tôi cũng có thể tạo một ByteSink để ghi byte của chúng tôi[]

ByteSink byteSink = Files.asByteSink[outputFile];
byteSink.write[dataForWriting];

ByteSink là đích đến mà chúng ta có thể ghi byte. Nó cung cấp một OutputStream đến đích

Nếu chúng ta cần sử dụng java. niô. các tập tin. Đường dẫn hoặc để cung cấp một OpenOption đặc biệt, chúng tôi có thể lấy ByteSink của mình bằng cách sử dụng lớp MoreFiles

ByteSink byteSink = MoreFiles.asByteSink[outputFile.toPath[], 
    StandardOpenOption.CREATE, 
    StandardOpenOption.WRITE];
byteSink.write[dataForWriting];

5. Apache Commons IO

Apache Commons IO cung cấp một số tác vụ tệp phổ biến

Hãy nhập phiên bản commons-io mới nhất


    commons-io
    commons-io
    2.11.0

Bây giờ, hãy viết byte[] của chúng ta bằng lớp FileUtils

FileUtils.writeByteArrayToFile[outputFile, dataForWriting];

FileUtils. writeByteArrayToFile tương tự như các phương thức khác mà chúng tôi đã sử dụng ở chỗ chúng tôi cung cấp cho nó một Tệp đại diện cho đích mong muốn của chúng tôi và dữ liệu nhị phân mà chúng tôi đang viết. Nếu tệp đích của chúng tôi hoặc bất kỳ thư mục mẹ nào không tồn tại, chúng sẽ được tạo

6. Phần kết luận

Trong hướng dẫn ngắn này, chúng ta đã học cách ghi dữ liệu nhị phân từ một byte[] vào một tệp bằng cách sử dụng Java đơn giản và hai thư viện tiện ích Java phổ biến. Google Guava và Apache Commons IO

Tất cả các tệp đều là nhị phân về mặt kỹ thuật, nghĩa là chúng được tạo thành từ một loạt các số 0 và 1. Tuy nhiên, khi chúng tôi đọc tệp ban đầu, chúng tôi đọc 8 bit hoặc 8 số 0 và 1 liên tiếp tại một thời điểm. 8 bit được gọi là byte và tệp văn bản lưu trữ một ký tự trong một byte. Vì vậy, nếu tôi có tệp văn bản 30 byte, điều đó có nghĩa là tệp chứa 30 ký tự

Khi chúng ta nói về các tệp nhị phân trong ngữ cảnh của bài giảng này, chúng ta đang nói về các tệp không tuân theo định dạng 1 byte, 1 ký tự. Thay vào đó, chúng tôi có định dạng tệp, chẳng hạn như tệp JPEG hoặc MP3. Chúng có định dạng mà các kỹ sư đã thiết kế. Ví dụ: JPEG phải có chiều rộng, chiều cao và danh sách các màu pixel để hiển thị hình ảnh. Có nhiều thứ khác đi vào tệp JPEG, nhưng tôi nghĩ bạn đã hiểu

Cấu trúc tệp nhị phân

Như tôi đã đề cập ở trên, các tệp nhị phân chỉ là các chuỗi 0 và 1. Không có cấu trúc vốn có. Ví dụ: nếu tôi đổi tên tệp JPEG của mình thành tệp TEXT, Windows sẽ cố mở tệp đó dưới dạng tệp văn bản. Điều này là do Windows chỉ nhìn thấy các số 0 và 1, nhưng phần mở rộng [. jpg] yêu cầu Windows mở nó dưới dạng JPEG. Nếu Windows biết điều này, nó có thể chạy một chương trình được thiết kế đặc biệt để đặt một thứ tự nhất định cho tệp JPEG

Ví dụ tệp nhị phân

Một ví dụ mà tôi thường sử dụng để chỉ ra cách hoạt động của tệp nhị phân là tệp bitmap. Đây là các tệp ảnh, giống như các tệp JPEG, nhưng không có giải nén phức tạp

Nhớ lại rằng một byte là 8 bit, là 8 số 0 và 1 ghép lại với nhau. Nói chung, nhưng không may là không phải lúc nào cũng vậy, các tệp nhị phân đơn vị địa chỉ nhỏ nhất sử dụng là một byte

Sau đây là những gì được gọi là tiêu đề, là cấu trúc được đặt thành 0 và 1 để chúng tôi biết những số 0 và 1 đó có nghĩa là gì. Đây là cấu trúc tiêu đề tệp bitmap

________số 8

Bạn có thể thấy ở trên rằng tất cả các kích thước không giống nhau. Vì vậy, trong tiêu đề tệp, chúng ta có thể biết đây là loại tệp bitmap nào bằng cách xem 16 số 0 và 1 mà tệp bắt đầu bằng

Đọc tập tin nhị phân

Chúng tôi có thể đọc các tệp nhị phân bằng cách thêm b vào chế độ được cung cấp để mở. Nhớ lại rằng chúng ta có thể mở một tệp, chẳng hạn như

Files.write[outputFile.toPath[], dataForWriting];
9. Trong trường hợp này, nó tìm kiếm myfile. txt và mở nó ra để đọc, đó là cái mà “r” dành cho. Khi chúng tôi đọc từ tệp, Python sẽ cung cấp cho chúng tôi các chuỗi vì nó nghĩ đây là tệp văn bản. Nhớ lại rằng một chuỗi chỉ là một dãy các ký tự

Nếu chúng ta muốn mở tệp dưới dạng một chuỗi các số 0 và 1 [nhị phân] thay vì một chuỗi ký tự [văn bản], chúng ta có thể thêm một “b” vào chế độ, viết tắt của nhị phân. Ví dụ,


    com.google.guava
    guava
    31.0.1-jre

0 sẽ mở tệp myfile. bin để đọc dưới dạng tệp nhị phân. Bây giờ chúng ta đã thêm “b”, Python sẽ cung cấp cho chúng ta kiểu dữ liệu byte thay vì chuỗi

Kiểu dữ liệu byte

Vì chúng tôi đang làm việc với byte chứ không phải chuỗi, nên Python đã thêm kiểu dữ liệu byte. Đây không phải là trường hợp trong các phiên bản Python cũ hơn, nhưng giờ đây kiểu dữ liệu này giúp việc đọc và ghi byte từ và đến một tệp dễ dàng hơn nhiều

Byte có thể được tạo bằng cách sử dụng một ký tự, trông giống như một chuỗi, nhưng nó bắt đầu bằng b, chẳng hạn như.


    com.google.guava
    guava
    31.0.1-jre

1. Mặc dù nó trông giống như một chuỗi, nhưng khi chúng ta gán nó cho một biến, đây sẽ là kiểu dữ liệu byte. Hãy nhớ rằng khi chúng ta cắt một chuỗi, chẳng hạn như
value = int[10].to_bytes[length=4, byteorder='little']
print[type[value]]
0 hoặc
value = int[10].to_bytes[length=4, byteorder='little']
print[type[value]]
1, chúng ta sẽ nhận được một ký tự hoặc chuỗi ký tự. Giống như thế này, chúng ta nhận được một byte đơn [8 bit] hoặc chuỗi byte

Nhận byte từ số

Các số nhị phân có thể được biểu diễn bằng một chuỗi các bit. Tuy nhiên, độ dài của nó hơi tùy ý. Ví dụ: 00000000023 là 23 cũng như 023 là 23. Tuy nhiên, nếu tôi chỉ có hai chữ số, tôi không thể đại diện cho 123. Vì vậy, tôi nói "tùy ý" bởi vì chúng ta có thể sử dụng nhiều chữ số hơn mức cần thiết, nhưng không ít hơn. Đây là lý do tại sao Python cho phép chúng ta chuyển đổi một số nguyên thành một chuỗi byte, nhưng để làm như vậy, chúng ta cần cung cấp cho nó một số tham số

Khi chúng ta có một đối tượng số nguyên [có nghĩa KHÔNG phải là chữ], chúng ta có thể gọi một hàm thành viên có tên là

value = int[10].to_bytes[length=4, byteorder='little']
print[type[value]]
2 để chuyển đổi nó thành một chuỗi byte. Tuy nhiên, hãy nhớ những gì tôi đã nói, chúng ta cần cung cấp cho nó một số tham số, cụ thể là hai. kích thước và tuổi thọ

Kích thước

Hầu hết các chuỗi byte trong máy tính đều có lũy thừa là 2. 1, 2, 4 hoặc 8 byte. Số byte chính xác cho mỗi trường tùy thuộc vào cấu trúc tệp mà bạn cần biết trước khi ghi hoặc đọc từ đó

độ bền

Endianness không khó hiểu đến thế, nhưng nó khác với những gì chúng ta đã nói trước đây. Endianness có nghĩa là phần cuối của số nào sẽ đến trước. Nó có hai hương vị. lớn hay nhỏ, nghĩa là chúng ta lưu đầu nhỏ [các chữ số ngoài cùng bên phải] trước hay đầu lớn [các chữ số ngoài cùng bên trái]. Hình dưới đây cho thấy có hai cách chúng ta có thể lưu trữ một số. lớn hay nhỏ

Ví dụ về đơn đặt hàng byte cuối lớn và nhỏ

Con người đọc bằng big-endian nếu bạn đọc từ trái sang phải. Bạn có thể thấy rằng số chúng tôi đang lưu trữ là 1a_2b_3c_4d_5e_6f_70_80. Đây là số cơ số 16 [thập lục phân]. Tuy nhiên, trong little endian, nó được lưu trữ ngược, vì phần cuối nhỏ [byte ngoài cùng bên phải] được lưu trữ trước

Chuyển đổi số nguyên thành byte

Một lần nữa, chúng ta có thể sử dụng to_bytes để tạo một chuỗi byte. Ví dụ

value = int[10].to_bytes[length=4, byteorder='little']
print[type[value]]

Trong đoạn mã trên, chúng tôi bắt buộc phải sử dụng int[10] vì hàm to_bytes hoạt động trên một đối tượng số nguyên chứ không phải số nguyên. Cũng giống như mọi thứ khác trong Python, có vô số cách để thực hiện thao tác này, tuy nhiên, tôi thấy cách này là dễ nhất

Có hai tham số bắt buộc đối với to_bytes, độ dài, là số byte và thứ tự byte, chỉ định xem thứ này sẽ được lưu trữ đầu nhỏ hay đầu lớn trước. Tham số byteorder lấy một chuỗi là 'lớn' hoặc 'nhỏ'

Khi chúng ta in kiểu biến mà chúng ta lấy lại, nó sẽ in như sau

Files.write[outputFile.toPath[], dataForWriting];
3

Vì vậy, chúng ta có một lớp byte một cách hợp pháp, chứa hàm to_bytes[] của chúng ta. Chúng tôi có thể ghi vào một tệp bằng cách sử dụng cùng một thao tác ghi, ngoại trừ bây giờ chúng tôi chuyển nó bytes[]. Ví dụ,

Files.write[outputFile.toPath[], dataForWriting];
4

Lưu ý rằng khi tôi viết, số byte để ghi vào tệp đến từ biến XX_bytes chứ không phải chính hàm ghi. Trong trường hợp này, chúng ta có thể chuyển đổi số nguyên thành byte bằng cách sử dụng to_bytes. Chúng tôi có thể chỉ định bao nhiêu byte chúng tôi muốn bằng cách chỉ định độ dài

Nếu bạn cố gắng chuyển đổi thành_bytes bằng cách sử dụng độ dài mà số nguyên không vừa, Python sẽ đưa ra lỗi OverflowError như bạn có thể thấy bên dưới

Files.write[outputFile.toPath[], dataForWriting];
5

Khi tôi chỉ định độ dài = 1, tôi đang nói với to_bytes rằng tôi muốn số nguyên vừa với một byte. Tuy nhiên, một byte [8 bit] sẽ đạt giá trị tối đa \[2^{8}-1=255\]. Điều này không chính xác 100% trong máy tính, nhưng tôi không muốn làm phức tạp mọi thứ. Khi chúng tôi lưu trữ các số âm, chúng tôi sử dụng một chút để lưu trữ dấu hiệu, vì vậy nó không hoàn toàn như thế này. Tuy nhiên, tôi chỉ đưa ra ví dụ này để cho thấy rằng có vấn đề khi chúng tôi lưu trữ các số lớn với độ dài nhỏ hơn

Từ byte

Phần trước đã hướng dẫn cách chuyển đổi từ kiểu số nguyên sang kiểu dữ liệu byte. Tuy nhiên, điều này thực sự chỉ hữu ích khi chúng ta viết byte. Điều gì xảy ra khi chúng ta muốn đọc byte từ tệp nhị phân?

Files.write[outputFile.toPath[], dataForWriting];
7

Bạn có thể thấy ở trên, chúng ta phải chỉ định byteorder một lần nữa khi chuyển đổi từ byte thành số nguyên. Chúng tôi không chỉ định độ dài vì chúng tôi biết độ dài từ chính đối tượng byte

Mảng byte

Một đối tượng bytes là bất biến, có nghĩa là chúng ta không thể sửa đổi nó tại chỗ, giống như một bộ dữ liệu. Chúng ta có thể tạo một đối tượng bytes mới để thực hiện một số phép biến đổi, nhưng nếu chúng ta chỉ muốn thay đổi một phần của đối tượng bytes thì sao? . Các đối tượng này rất giống với các đối tượng byte, tuy nhiên chúng có thể được thay đổi tại chỗ, giống như một danh sách

Chúng ta có thể thay đổi đối tượng bytes thành đối tượng bytearray bằng cách sử dụng bytearray[bytes_object] và ngược lại

Files.write[outputFile.toPath[], dataForWriting];
8

Đoạn mã trên lấy một đối tượng bytes, sao chép nó vào một mảng byte, thay đổi 's' thành 'z' và sao chép lại. Lưu ý rằng tôi phải sử dụng ord[“z”], đây là một hàm đặc biệt cung cấp cho tôi biểu diễn số nguyên của chữ thường z

GHI CHÚ. Đọc và ghi vào tệp nhị phân sử dụng đối tượng byte bất biến. Tuy nhiên, như bạn có thể thấy ở trên, bạn có thể chuyển đổi sang và từ

Làm cách nào để chuyển đổi byte thành CSV bằng Python?

Giải pháp nhanh .
Chuyển đổi đối tượng byte thành chuỗi bằng cách sử dụng str[] và cắt [2. -1] để loại bỏ "b". '" kèm theo ký hiệu
Chuyển đổi chuỗi thành chuỗi có định dạng CSV bằng cách sử dụng chuỗi. thay thế ['\\t', ',']. .
Ghi CSV vào một tệp bằng cách sử dụng hàm print[] với file=open[. , 'w'] đối số

Tôi có thể ghi vào tệp bằng Python không?

Python cung cấp cho chúng ta hai phương thức để ghi vào tệp văn bản. phương thức write[] để chèn một chuỗi vào một dòng trong tệp văn bản. phương thức writelines[] để chèn đồng thời nhiều chuỗi từ danh sách các chuỗi vào tệp văn bản .

Chủ Đề