Cách đơn giản nhất (ít nhất là lỗi, ít dòng mã nhất, tuy nhiên bạn muốn diễn giải nó) để mở tệp trong C và đọc nội dung của tệp đó thành một chuỗi (char * , char [], bất cứ điều gì)?Cách dễ nhất để lấy nội dung của tệp trong C
Trả lời
Tôi có xu hướng chỉ tải toàn bộ bộ đệm dưới dạng bộ nhớ thô vào bộ nhớ và tự phân tích cú pháp. Bằng cách đó, tôi có quyền kiểm soát tốt nhất những gì lib tiêu chuẩn thực hiện trên nhiều nền tảng.
Đây là sơ khai tôi sử dụng cho việc này. bạn cũng có thể kiểm tra mã lỗi cho fseek, ftell và fread. (bỏ qua cho rõ ràng).
char * buffer = 0;
long length;
FILE * f = fopen (filename, "rb");
if (f)
{
fseek (f, 0, SEEK_END);
length = ftell (f);
fseek (f, 0, SEEK_SET);
buffer = malloc (length);
if (buffer)
{
fread (buffer, 1, length, f);
}
fclose (f);
}
if (buffer)
{
// start to process your data/extract strings here...
}
Tuyệt vời, hoạt động như một sự quyến rũ (và khá đơn giản để theo dõi). Cảm ơn! –
Tôi cũng sẽ kiểm tra giá trị trả về của fread, vì nó có thể không thực sự đọc toàn bộ tập tin do lỗi và những gì không. – freespace
Dọc theo các dòng của những gì freespace nói, bạn có thể muốn kiểm tra để đảm bảo các tập tin không phải là rất lớn. Giả sử, một người nào đó đã quyết định nuôi một tệp 6 GB vào chương trình đó ... – rmeador
Nếu "đọc nội dung của nó thành một chuỗi" có nghĩa là các tập tin không chứa các ký tự với mã 0, bạn cũng có thể sử dụng getdelim() chức năng, mà một trong hai chấp nhận một khối bộ nhớ và reallocates nó nếu cần thiết, hoặc chỉ cấp phát toàn bộ bộ đệm cho bạn và đọc tệp vào bộ đệm cho đến khi nó gặp dấu phân tách hoặc kết thúc tệp. Chỉ cần vượt qua '\ 0' làm dấu phân tách để đọc toàn bộ tệp.
Chức năng này có sẵn trong thư viện GNU C, http://www.gnu.org/software/libc/manual/html_mono/libc.html#index-getdelim-994
Mẫu mã có thể trông đơn giản như
char* buffer = NULL;
size_t len;
ssize_t bytes_read = getdelim(&buffer, &len, '\0', fp);
if (bytes_read != -1) {
/* Success, now the entire file is in the buffer */
Tôi đã sử dụng nó trước đây! Nó hoạt động rất độc đáo, giả sử tập tin bạn đang đọc là văn bản (không chứa \ 0). – ephemient
NICE! Tiết kiệm rất nhiều vấn đề khi slurping trong toàn bộ tập tin văn bản. Bây giờ nếu có một cách cực kỳ đơn giản tương tự như đọc một luồng tệp nhị phân cho đến EOF mà không cần bất kỳ ký tự phân cách nào! – anthony
khác, không may đánh giá cao hệ điều hành phụ thuộc, giải pháp là bộ nhớ ánh xạ tập tin. Những lợi ích thường bao gồm hiệu suất của việc đọc, và giảm sử dụng bộ nhớ khi các ứng dụng xem và bộ nhớ cache của hệ điều hành thực sự có thể chia sẻ bộ nhớ vật lý.
đang POSIX sẽ trông như thế này:
int fd = open("filename", O_RDONLY);
int len = lseek(fd, 0, SEEK_END);
void *data = mmap(0, len, PROT_READ, MAP_PRIVATE, fd, 0);
Windows trên Mặt khác là phức tạp hơn chút, và tiếc là tôi không có một trình biên dịch trước mặt tôi để kiểm tra, nhưng các chức năng được cung cấp bởi CreateFileMapping()
và MapViewOfFile()
.
Đừng quên kiểm tra giá trị trả lại từ các cuộc gọi hệ thống đó! –
Nếu tệp là văn bản và bạn muốn nhận dòng văn bản theo dòng, cách dễ nhất là sử dụng fgets().
char buffer[100];
FILE *fp = fopen("filename", "r"); // do not use "rb"
while (fgets(buffer, sizeof(buffer), fp)) {
... do something
}
fclose(fp);
Nếu bạn đang đọc file đặc biệt như stdin hoặc một đường ống, bạn sẽ không thể sử dụng fstat để có được kích thước tập tin trước đó. Ngoài ra, nếu bạn đang đọc một tập tin nhị phân fgets là sẽ mất thông tin kích thước chuỗi vì nhúng '\ 0' ký tự. Cách tốt nhất để đọc một tập tin sau đó là sử dụng đọc và realloc:
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
int main() {
char buf[4096];
ssize_t n;
char *str = NULL;
size_t len = 0;
while (n = read(STDIN_FILENO, buf, sizeof buf)) {
if (n < 0) {
if (errno == EAGAIN)
continue;
perror("read");
break;
}
str = realloc(str, len + n + 1);
memcpy(str + len, buf, n);
len += n;
str[len] = '\0';
}
printf("%.*s\n", len, str);
return 0;
}
Đây là O (n^2), trong đó n là độ dài của tệp của bạn. Tất cả các giải pháp với nhiều upvotes hơn này là O (n). Xin vui lòng không sử dụng giải pháp này trong thực tế, hoặc sử dụng một phiên bản sửa đổi với sự tăng trưởng nhân. –
realloc() có thể mở rộng bộ nhớ hiện tại sang kích thước mới mà không cần sao chép bộ nhớ cũ sang một bộ nhớ lớn hơn mới. chỉ khi có các cuộc gọi can thiệp đến malloc() nó sẽ cần phải di chuyển bộ nhớ xung quanh và làm cho giải pháp này O (n^2). ở đây, không có lệnh gọi hàm malloc() nào xảy ra giữa các lệnh gọi đến realloc() để giải pháp sẽ ổn. – Jake
Bạn có thể đọc trực tiếp vào bộ đệm "str" (với độ lệch thích hợp), mà không cần phải sao chép từ một "buf" trung gian. Tuy nhiên, kỹ thuật đó thường sẽ cấp phát bộ nhớ cần thiết cho nội dung tập tin. Ngoài ra xem ra cho các tập tin nhị phân, printf sẽ không xử lý chúng một cách chính xác, và bạn có thể không muốn in nhị phân anyway! – anthony
// Assumes the file exists and will seg. fault otherwise.
const GLchar *load_shader_source(char *filename) {
FILE *file = fopen(filename, "r"); // open
fseek(file, 0L, SEEK_END); // find the end
size_t size = ftell(file); // get the size in bytes
GLchar *shaderSource = calloc(1, size); // allocate enough bytes
rewind(file); // go back to file beginning
fread(shaderSource, size, sizeof(char), file); // read each char into ourblock
fclose(file); // close the stream
return shaderSource;
}
Đây là một giải pháp khá thô bởi vì không có gì được kiểm tra đối chiếu null.
Điều này sẽ chỉ với các tệp dựa trên đĩa. Nó sẽ thất bại cho các đường ống được đặt tên, đầu vào tiêu chuẩn hoặc luồng mạng. – anthony
Ha, cũng là lý do tôi đến đây! Nhưng tôi nghĩ rằng bạn cần hoặc là null chấm dứt chuỗi, hoặc trả về độ dài mà 'glShaderSource' tùy chọn mất. –
Nếu bạn đang sử dụng glib
, thì bạn có thể sử dụng g_file_get_contents;
gchar *contents;
GError *err = NULL;
g_file_get_contents ("foo.txt", &contents, NULL, &err);
g_assert ((contents == NULL && err != NULL) || (contents != NULL && err == NULL));
if (err != NULL)
{
// Report error to user, and free error
g_assert (contents == NULL);
fprintf (stderr, "Unable to read file: %s\n", err->message);
g_error_free (err);
}
else
{
// Use file contents
g_assert (contents != NULL);
}
}
Chỉ cần sửa đổi từ câu trả lời được chấp nhận ở trên.
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
char *readFile(char *filename) {
FILE *f = fopen(filename, "rt");
assert(f);
fseek(f, 0, SEEK_END);
long length = ftell(f);
fseek(f, 0, SEEK_SET);
char *buffer = (char *) malloc(length + 1);
buffer[length] = '\0';
fread(buffer, 1, length, f);
fclose(f);
return buffer;
}
int main() {
char *content = readFile("../hello.txt");
printf("%s", content);
}
Đây không phải là mã C. Câu hỏi không được gắn thẻ là C++. – Gerhardh
@Gerhardh Vì vậy, phản ứng nhanh chóng với câu hỏi chín năm trước khi tôi đang chỉnh sửa! Mặc dù phần chức năng là C thuần khiết, tôi xin lỗi vì câu trả lời không-chạy-trên-c của tôi. – BaiJiFeiLong
Câu hỏi cổ này được liệt kê ở đầu câu hỏi đang hoạt động. Tôi đã không tìm kiếm nó. – Gerhardh
- 1. cách lấy nội dung của tệp ascii nhỏ trong python?
- 2. cách lấy ParcelFileDescriptor cho nội dung tệp?
- 3. Cách lấy nội dung của thẻ HTML?
- 4. Cách lấy nội dung từ tệp từ URL này?
- 5. Trong VisualStudio DTE, cách lấy nội dung của ActiveDocument?
- 6. Lấy nội dung của một tệp bằng PHP FTP
- 7. Lấy nội dung tệp bằng FTPClient Java
- 8. Cách tốt nhất để xử lý nội dung của sysfs bằng C/C++ là gì?
- 9. cách lấy (txt) nội dung tệp từ FileField?
- 10. Không thể lấy nội dung bên trong của '' vì nội dung không phải là chữ số
- 11. Cách dễ nhất để lấy tiêu đề từ tệp CSV trong Ruby là gì?
- 12. Được sao chép cách duy nhất để lấy nội dung của một kho lưu trữ Mercurial?
- 13. Cách lấy nội dung/loại tệp tại thời gian chạy
- 14. SAX: Cách lấy nội dung của một phần tử
- 15. Làm cách nào để lấy một loại nội dung của một tệp bằng Python? (Với url ..)
- 16. Lấy nội dung XML của SimpleXMLElement
- 17. Cách dễ nhất để tải xuống tệp?
- 18. Làm cách nào để xóa toàn bộ nội dung của tệp trong C?
- 19. Lấy nội dung của DIV bằng cách sử dụng JavaScript
- 20. Cách xóa nội dung của tệp trong python
- 21. Cách lấy nội dung của nút từ JDOM
- 22. Cách lấy git để hợp nhất chính xác nội dung đã di chuyển (không chỉ các tệp)
- 23. Cách lấy nội dung của giỏ hàng Amazon?
- 24. cách đọc nội dung của tệp trong Erlang?
- 25. Làm cách nào để gửi nội dung của tệp dưới dạng email trong Perl?
- 26. Làm cách nào để ghi đè nội dung tệp bằng nội dung mới trong PHP?
- 27. Lấy nội dung của nút XML bằng cách sử dụng C#
- 28. Làm cách nào để giải nén nội dung của tệp JavaScript?
- 29. Tôi có thể lấy nội dung của tệp được tải lên bằng php bằng cách nào?
- 30. Cách dễ nhất để lấy các tập tin của tập tin từ xa trong PHP?
"cách đơn giản nhất" và "ít xảy ra lỗi" thường là sự đối lập lẫn nhau. –
"cách đơn giản nhất" và "ít bị lỗi nhất" thực sự đồng nghĩa trong sách của tôi. Ví dụ, câu trả lời trong C# là 'string s = File.ReadAllText (filename);'.Làm thế nào có thể được đơn giản hơn và dễ bị lỗi hơn? –