2011-11-24 27 views
5

Có phương pháp nào để tôi có thể chia nhỏ tệp văn bản trong java mà không đọc nó không?Tách tệp văn bản mà không đọc nó

Tôi muốn xử lý tệp văn bản lớn trong GB, vì vậy tôi muốn chia nhỏ tệp trong các phần nhỏ và áp dụng chuỗi trên mỗi tệp và kết hợp kết quả cho tệp đó.

Vì tôi sẽ đọc nó cho các phần nhỏ sau đó tách tệp bằng cách đọc nó sẽ không có ý nghĩa gì vì tôi sẽ phải đọc cùng một tệp cho hai lần và nó sẽ làm giảm hiệu suất của tôi.

+0

thẻ "tệp" được đề xuất –

Trả lời

2

Nỗ lực luồng của bạn bị hỏng. Nếu bạn phải làm chế biến đáng kể với dữ liệu tập tin của bạn xem xét sau cấu trúc luồng:

1 đọc Chủ đề (Đọc File và nguồn cấp dữ liệu người lao động)

  • Queue với khối đọc

1. .n Chủ đề công nhân (n phụ thuộc vào lõi CPU của bạn, xử lý các khối dữ liệu từ chủ đề đọc)

  • Hàng đợi hoặc từ điển với khối đã xử lý

1 Writer Thread (Ghi kết quả vào một số tập tin)

Có lẽ bạn có thể kết hợp các chủ đề Reader/Writer thành một thread bởi vì nó không có ý nghĩa nhiều parallelize IO trên đĩa cứng vật lý như nhau.

Rõ ràng là bạn cần một số nội dung đồng bộ hóa giữa các chuỗi. Đặc biệt đối với hàng đợi, hãy nghĩ về semaphores

+0

gợi ý tuyệt vời tôi chắc chắn sẽ cố gắng này. – RamIndani

2

Nếu không đọc nội dung của tệp, bạn không thể thực hiện điều đó. Chuyện đó không thể xảy ra được.

1

Có điều gì đó phải đọc tệp của bạn để chia nhỏ tệp đó (và bạn có thể muốn chia nhỏ nó ở hàng rào, có thể không phải ở nhiều kilobyte).

Nếu chạy trên máy Linux, bạn có thể ủy quyền chia tách thành lệnh bên ngoài như csplit. Vì vậy, chương trình Java của bạn sẽ chỉ cần chạy một lệnh csplit yourbigfile.txt.

+0

Lệnh bên ngoài sẽ đọc tệp và chia nhỏ tệp đó. Lợi ích ở đâu? –

+0

Tránh làm điều đó trong Java. Có lẽ đơn giản hơn để mã (vì tiện ích đã tồn tại). Có lẽ nhanh hơn (nhưng tôi sẽ không đặt cược điều đó). –

+0

xin lỗi tôi quên đề cập đến tôi đang làm việc trên windowsXP bất kỳ gợi ý khác sẽ là một trợ giúp tuyệt vời. – RamIndani

2

Tôi không nghĩ rằng đây có thể vì những lý do sau đây:

  1. Làm thế nào để bạn viết một tập tin mà không cần "đọc" nó?
  2. Bạn sẽ cần phải đọc trong văn bản để biết ranh giới ký tự ở đâu (mã hóa không nhất thiết phải là 1 byte). Điều này có nghĩa là bạn không thể xử lý tệp dưới dạng nhị phân.

Thực sự không thể đọc từng dòng và xử lý nó như vậy? Điều đó cũng tiết kiệm không gian bổ sung mà các tập tin phân chia sẽ mất cùng với bản gốc. Để bạn tham khảo, việc đọc một tệp văn bản chỉ đơn giản là:

public static void loadFileFromInputStream(InputStream in) throws IOException { 
    BufferedReader inputStream = new BufferedReader(new InputStreamReader(in)); 

    String record = inputStream.readLine(); 
    while (record != null) { 
    // do something with the record 
    // ... 
    record = inputStream.readLine(); 
    } 
} 

Bạn chỉ đọc một dòng tại một thời điểm ... do đó kích thước tệp không ảnh hưởng đến hiệu suất. Bạn cũng có thể dừng bất kỳ lúc nào bạn phải làm. Nếu bạn đang mạo hiểm, bạn cũng có thể thêm các dòng để phân tách các chủ đề để tăng tốc độ xử lý. Bằng cách đó, IO có thể tiếp tục khuấy động trong khi bạn xử lý dữ liệu của mình.

Chúc may mắn! Nếu vì một lý do nào đó, bạn tìm được giải pháp, hãy đăng nó ở đây. Cảm ơn!

+0

tôi đã thực hiện nó bằng cách sử dụng dòng theo phương pháp trong BufferedReader nhưng tôi đang cố gắng cho hiệu suất tốt hơn tốc độ thực hiện tốt hơn. – RamIndani

2

Nói một cách kỹ thuật - không thể thực hiện được mà không đọc tệp. Nhưng bạn cũng không cần phải giữ toàn bộ nội dung tập tin trong bộ nhớ để làm việc tách. Chỉ cần mở một luồng vào tệp và ghi ra các tệp khác bằng cách chuyển hướng đầu ra sang tệp khác sau khi một số byte nhất định được ghi vào một tệp. Bằng cách này, bạn không cần phải giữ nhiều hơn một byte dữ liệu tệp trong bộ nhớ tại bất kỳ thời điểm nào. Nhưng có một bộ đệm lớn hơn, khoảng 8 hoặc 16kb sẽ tăng đáng kể hiệu suất.

1

Theo nghĩa đen, không. Để phân chia một tệp thành các tệp nhỏ hơn, bạn phải đọc tệp lớn và viết tệp nhỏ hơn.

Tuy nhiên, tôi nghĩ bạn thực sự muốn biết liệu bạn có thể có các chuỗi khác nhau liên tục đọc "các phần" khác nhau của một tệp cùng một lúc hay không. Và câu trả lời là bạn có thể làm điều đó. Chỉ cần mỗi chủ đề tạo đối tượng RandomAccessFile riêng cho tệp, seek đến địa điểm có liên quan và bắt đầu đọc.

(A FileInputStream có lẽ sẽ làm việc quá, mặc dù tôi không nghĩ rằng API đặc tả Java đảm bảo rằng skip được thực hiện sử dụng một mức hệ điều hành "tìm kiếm" hoạt động trên các tập tin.)

Có một vài biến chứng có thể:

  • Nếu tập tin là văn bản, bạn có lẽ muốn mỗi thread để bắt đầu chế biến lúc bắt đầu của một số dòng trong tập tin. Vì vậy, mỗi thread phải bắt đầu bằng cách tìm kết thúc của một dòng, và chắc chắn rằng nó đọc đến cuối dòng cuối cùng trong "phần" của nó.

  • Nếu tệp sử dụng mã hóa ký tự có chiều rộng thay đổi (ví dụ: UTF-8), thì bạn cần xử lý trường hợp ranh giới phân vùng của bạn nằm ở giữa ký tự.

+0

Tôi đã suy nghĩ của một RandomAccessFile, nhưng làm thế nào để bạn giải quyết vấn đề với ranh giới ký tự cho các chương trình mã hóa không byte? tức là UTF-16, v.v. –

+1

@JacoVanNiekerk - bởi một số chương trình nhận biết mã hóa cẩn thận. Ví dụ, với UTF-16 và UTF-8, lược đồ mã hóa đảm bảo rằng bạn có thể đồng bộ hóa lại với một ranh giới ký tự (thực) trong một số lượng nhỏ các byte. –

+0

RandomAccessFile có vẻ là tốt nhưng tôi đoán nó hoạt động trên byte đó là kỹ thuật đọc chậm hơn so với đọc dòng. hãy sửa tôi nếu tôi sai. – RamIndani

Các vấn đề liên quan