리눅스에서 txt 파일의 특정 내용을 읽어보려고 합니다

익명 사용자의 이미지

아래글 글쓴이입니다.

죄송합니다, 해당 글을 편집을 하려 했지만 깜박하고 로그인을 안해서 그런지 수정이 불가피 해져서 다시 새로 글을 쓰게 되었습니다 ㅠㅠ

리눅스에서 txt파일을 읽어들여 해당 파일의 특정 내용을 읽어보기 위한 코드를 찾던중 샘플 코드를 하나 구하여 윈도우에서 테스트로 한번 빌드해 보았습니다

테스트를 위한 test.txt파일의 내용은 아래 두줄이 전부입니다

[test]
value=1

윈도우의 ini파일과 비슷한 형식입니다.

코드를 작성한 목적은 윈도우의 ini파일에서의 특정값 로딩처럼 함수로 [test] 안의 value 값을 읽어서 1이라는 값을 리턴받기 위한 코드입니다.

사용한 코드는 아래와 같습니다

#include <stdio.h>
 
int                 iFoundTopic;
int                 iFoundItem;
int                 iError;
long                lTopicFilePos;
char                acTopicHeading[80];
char                acLastTopicHeading[80];
char                acItemHeading[80];
char                acIniLine[160];
char                acIniPath[160];
char                acTempPath[160];
FILE                *pFIniFile;
FILE                *pFTempIni;
 
 
// readinis
// read configuration string
int readinis(char *pacPath, char *pacTopic, char *pacItem, char *pacValue) {
	int                 iItemLength;
	int                 iValueLength;
	char                *pcLastCharacter;
 
	iError = 0;
 
	strcpy(acIniPath, pacPath);
 
	// add brackets to topic
	strcpy(acTopicHeading, "[");
	strcat(acTopicHeading, pacTopic);
	strcat(acTopicHeading, "]\n");
 
	strcpy(acItemHeading, pacItem);
	strcat(acItemHeading, "=");
 
	iItemLength = strlen(acItemHeading);
 
	iFoundTopic = 0;
	iFoundItem = 0;
 
	// try to open current config file for reading
	if ((pFIniFile = fopen(acIniPath, "r")) != NULL) {
		// has the topic been found before
		if (strcmp(acLastTopicHeading, acTopicHeading) == 0) {
			iFoundTopic = 1;
			fseek(pFIniFile, lTopicFilePos, SEEK_SET);
		}
 
		// read a line from the config file until EOF
		while (fgets(acIniLine, 159, pFIniFile) != NULL) {
			// topic has not been found yet
			if (iFoundTopic == 0) {
				if (strcmp(acTopicHeading, acIniLine) == 0) {
					// found the topic
					iFoundTopic = 1;
					lTopicFilePos = ftell(pFIniFile);
					strcpy(acLastTopicHeading, acTopicHeading);
				}
				continue;
			}
			// the item has not been found yet
			if ((iFoundItem == 0) && (iFoundTopic == 1)) {
				// if newline or [, the end of the topic has been reached
				// no config value in file yet
				if ((acIniLine[0] == '\n') || (acIniLine[0] == '[')) {
					iFoundItem = 1;
					break;
				}
 
				if (strncmp(acItemHeading, acIniLine, iItemLength) == 0) {
					// found the item
					iFoundItem = 1;
					strcpy(pacValue, &acIniLine[iItemLength]);
					continue;
				}
			}
		}
		fclose(pFIniFile);
	}
	// remove trailing comment
	iValueLength = strlen(pacValue);
	while (iValueLength) {
		if (*(pacValue + iValueLength) == '#') {
			*(pacValue + iValueLength) = '\0';
		}
		iValueLength--;
	}
	// remove trailing white space
	while ((iValueLength = strlen(pacValue)) > 0) {
		pcLastCharacter = (pacValue + iValueLength - 1);
		if ((*pcLastCharacter == ' ')
			|| (*pcLastCharacter == '\n')
			|| (*pcLastCharacter == '\r')
			|| (*pcLastCharacter == '\t')
			|| (*pcLastCharacter == '\v')
			|| (*pcLastCharacter == '\a')
			|| (*pcLastCharacter == '\b')
			|| (*pcLastCharacter == '\f')) {
			*pcLastCharacter = '\0';
		}
		else {
			break;
		}
	}
 
	return (iError);
}
 
 
int main()
{
	char acValue[160];
	acLastTopicHeading[0] = '\0'; // initialize
	readinis("test.txt", "test", "value", acValue);
	printf("%s\n", acValue);
 
	getchar();
 
	return 0;
}

main함수에서 "test.txt" 파일을 경로로 [test]안의 value 값을 읽을 readinis 함수를 호출하고 위 함수 내용은 문서내에 특정기호('[' or ']') 나 개행입력('\n') 등을 캐치하여 특정값을 잡아내기 위한 코드입니다.

해당 코드가 윈도우에선 잘 돌아가나 리눅스에선 파일은 읽어지나 값을 못읽는 것으로 보아 예상되는 문제는 리눅스에선 개행문자'\n' 등이 다른가? 하는 생각이 드는대 어디까지나 추측이라...

해당 코드의 문제점을 고수님들의 조언을 여쭙고자 질문을 올리게 되었습니다.

조언을 해주신다면 감사드리겠습니다

jachin의 이미지

출력이 잘 되는데요? :)

#include <string.h>

혹시 헤더 빼먹은 것 때문은 아니겠지요?

실제론 정규표현식 라이브러리 쓰시길 권장해드리고 싶지만...넵. 잘 동작합니다.

글쓴이의 이미지

직접 코드 테스트 까지 해주셔서 너무 감사드립니다.
string.h는 사용하고 있으며 말씀하신 정규표현식 라이브러리라는게 어떤건지 혹시 한번 여쭈어 볼 수 있을까요?

jachin의 이미지

아마 헤더파일이 이미 있긴 할 겁니다.
#include <regex.h>

https://stackoverflow.com/questions/1085083/regular-expressions-in-c-examples

위의 글의 내용을 보시고, 한 번 시도해 보시길 바랍니다.

글쓴이의 이미지

참고하여 진행해보겠습니다

karkayan의 이미지

혹시 윈도우에서 만든 txt 파일을 그대로 리눅스로 복사해서 쓰신건 아닌가요?
윈도우에서는 \r\n, 리눅스에서는 \n을 개행문자로 사용합니다. 그래서 윈도우에서 만든 txt 파일자체를 리눅스로 복사해서 사용하면 잘 안될수도 있습니다.
리눅스에서 dos2unix 같은 툴을 사용해서 개행문자를 리눅스식으로 바꿔보세요.

글쓴이의 이미지

두가지 작업을 해보았는대
말씀하신것처럼 윈도우에서 만든 txt파일을 그대로 복사해서 한번 해봤는대 값을 읽는대 실패하였습니다
두번째로는 윈도우에서 복사한 txt파일의 내용을 복사하여 리눅스에서 새로 만든 txt파일에 붙여넣기 하였는대 읽지 못하였습니다

이 두번째 작업시에도 윈도우 개행문자가 섞여들어가는건지 의심되긴 합니다

raymundo의 이미지

저도 저 코드 가지고 그대로 해봤는데 잘 읽고 나오더군요.

코드 곳곳에 printf라도 넣어서 해당 입력라인을 읽을 때 어떻게 분기하는지 보셨나요?

그리고 리눅스에서 hexdump -C test.txt 해서 줄바꿈 문자가 0a만 있는지 0d 0a가 있는지 확인할 수 있습니다.

좋은 하루 되세요!

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.