Jak odczytać plik bez znaku nowej linii?


374

W Pythonie dzwonienie

temp = open(filename,'r').readlines()

daje listę, w której każdy element jest linią w pliku. Jest to trochę głupie, ale nadal: readlines()zapisuje także znak nowego wiersza do każdego elementu, czego nie chciałbym wydarzyć.

Jak mogę tego uniknąć?


4
Zastosowanie taśmy: [l.strip('\n\r') for l in temp]. Lub nawet rstrip. A ponieważ iteracja tutaj może być in openzamiast in temp.
gorlum0

11
Byłoby miło, gdyby w Pythonie 3 istniała wartość pozwalająca ustawić newlineargument open na te gryzące końcowe wiersze.
jxramos

Odpowiedzi:


554

Możesz odczytać cały plik i linie podziału za pomocą str.splitlines:

temp = file.read().splitlines()

Lub możesz ręcznie usunąć nową linię:

temp = [line[:-1] for line in file]

Uwaga: to ostatnie rozwiązanie działa tylko wtedy, gdy plik kończy się na nowej linii, w przeciwnym razie ostatnia linia straci znak.

To założenie jest prawdziwe w większości przypadków (szczególnie w przypadku plików utworzonych przez edytorów tekstowych, które często zrobienia dodać kończący znak nowej linii w każdym razie).

Jeśli chcesz tego uniknąć, możesz dodać nowy wiersz na końcu pliku:

with open(the_file, 'r+') as f:
    f.seek(-1, 2)  # go at the end of the file
    if f.read(1) != '\n':
        # add missing newline if not already present
        f.write('\n')
        f.flush()
        f.seek(0)
    lines = [line[:-1] for line in f]

Lub prostszą alternatywą jest stripzamiast nowej linii:

[line.rstrip('\n') for line in file]

Lub nawet, chociaż dość nieczytelne:

[line[:-(line[-1] == '\n') or len(line)+1] for line in file]

Który wykorzystuje fakt, że zwracana wartość ornie jest wartością logiczną, ale obiektem, który został oceniony jako prawda lub fałsz.


readlinesMetoda jest rzeczywiście równoważne:

def readlines(self):
    lines = []
    for line in iter(self.readline, ''):
        lines.append(line)
    return lines

# or equivalently

def readlines(self):
    lines = []
    while True:
        line = self.readline()
        if not line:
            break
        lines.append(line)
    return lines

Ponieważ readline()utrzymuje nową linię, również readlines()ją utrzymuje.

Uwaga: dla symetrii do readlines()tej writelines()metody jest nie dodać kończące znaki nowej linii, więc f2.writelines(f.readlines())tworzy dokładną kopię fw f2.


1
Pamiętaj, że [line.rstrip('\n') for line in file]usuniesz więcej niż jeden końcowy \n.
Wes Turner,

1
Mówiąc prościej, [line[:-(line[-1] == '\n') or len(line)+1] for line in file]może zamiast tego być [line[:-(line[-1] == '\n') or None] for line in file].
Wes Turner,

10
Te rozwiązania wczytują cały plik do pamięci. Zmiana nawiasów kwadratowych opisu listy na nawiasy tworzy wyrażenie generujące, które pozwala na iterację po pliku po jednym wierszu na raz: for line in (x.strip() for x in f):
Joseph Sheedy,

2
@velotron To nie jest tak naprawdę pytanie / odpowiedź. Ponadto: pamiętaj, że withzamyka pliki po zakończeniu bloku, co oznacza, że ​​nie możesz tego robić with open(...) as f: lines = (line for line in f)i używać linespoza, withponieważ pojawi się błąd we / wy. Możesz być leniwy, używając genexp, ale musisz go zużyć przed zamknięciem pliku.
Bakuriu

@WesTurner. Ale nie będzie więcej niż jedna nowa linia. Dodatkowa nowa linia będzie częścią następnej pustej linii
Szalony fizyk

38
temp = open(filename,'r').read().split('\n')

14
Co by się jednak stało z \r\nnowymi liniami? ;)
Wolph

26
Python automatycznie obsługuje uniwersalne znaki nowej linii, dzięki czemu .split('\n')podzieli się poprawnie, niezależnie od konwencji nowej linii. Miałoby to znaczenie, jeśli czytasz plik w trybie binarnym. W takim przypadku splitlines()obsługuje uniwersalne znaki nowej linii, podczas gdy split('\n')nie.
Bakuriu

7
I zawsze jest os.linesep:)
askewchan

1
@ LarsH, w niektórych przypadkach pomogłoby to, że w moim systemie \r\nzakończenia linii nie są konwertowane \n, czy to czytane jako tekstowe, czy binarne, więc os.linesepdziałałyby tam, gdzie \nnie. Ale splitlinesjest wyraźnie lepszym wyborem, w przypadku, gdy wspominasz, gdzie plik nie pasuje do systemu operacyjnego. Naprawdę wspomniałem o tym głównie na wypadek, gdyby ludzie przyglądający się tej dyskusji nie byli świadomi jej istnienia.
askewchan

1
@askewchan Być może korzystasz z nieaktualnej wersji Pythona. Wierzę, że od Python 3 uniwersalne znaki nowej linii są domyślnie włączone, tzn. \r\nBędą konwertowane na pliki tekstowe, nawet jeśli pracujesz w systemie Linux.
Arthur Tacca,

13

inny przykład:

Odczytywanie pliku po jednym wierszu naraz. Usuwanie niechcianych znaków z końca łańcuchastr.rstrip(chars)

with open(filename, 'r') as fileobj:
    for row in fileobj:
        print( row.rstrip('\n') )

patrz także str.strip([chars])istr.lstrip([chars])

(python> = 2.0)


10
temp = open(filename,'r').read().splitlines()

5
Czy jesteś pewien, że to zamyka plik? Myślę, że tak nie jest, więc tak naprawdę nie jest to jedna linijka ...
Ray Hulha

9

Myślę, że to najlepsza opcja.

temp = [line.strip() for line in file.readlines()]

8
To rozwiązanie usuwa również spacje wiodące i końcowe, co nie jest zamierzone.
Roland Illig

Jednak zrozumienie jest naprawdę miłe. Przynajmniej w Pythonie 3 można użyć, temp = [line.rstrip() for line in file.readlines()]aby uzyskać to, co przeznaczone są notatki @Roland_Illig.
bballdave025

Jeśli masz zamiar powtarzać wszystkie linie, dlaczego nie leniwie? Dzięki .readlines(), skutecznie powtarzasz dwukrotnie cały plik.
AMC

1

Spróbuj tego:

u=open("url.txt","r")  
url=u.read().replace('\n','')  
print(url)  

4
Ten fragment kodu może rozwiązać pytanie, ale wyjaśnienie naprawdę pomaga poprawić jakość posta. Pamiętaj, że w przyszłości odpowiadasz na pytanie czytelników, a ci ludzie mogą nie znać przyczyn Twojej sugestii kodu. Staraj się również nie tłoczyć kodu objaśniającymi komentarzami, ponieważ zmniejsza to czytelność zarówno kodu, jak i objaśnień!
Do widzenia StackExchange

Nie rozumiem, dlaczego ktokolwiek miałby to wykorzystywać w stosunku do niektórych alternatywnych rozwiązań.
AMC

-1
my_file = open("first_file.txt", "r")
for line in my_file.readlines():
    if line[-1:] == "\n":
        print(line[:-1])
    else:
        print(line)
my_file.close() 

3
Dodaj wyjaśnienie, aby było przydatne dla innych.
samuellawrentz

Do obsługi obiektu pliku należy użyć menedżera kontekstu i bezpośrednio iterować plik. Korzystając z .readlines()tego w ten sposób, skutecznie iterujesz dwa razy cały plik.
AMC

-2
import csv

with open(filename) as f:
    csvreader = csv.reader(f)
    for line in csvreader:
         print(line[0])

2
Ale co jeśli linia zawiera przecinek?
gilch

-8
def getText():
    file=open("ex1.txt","r");

    names=file.read().split("\n");
    for x,word in enumerate(names):
        if(len(word)>=20):
            return 0;
            print "length of ",word,"is over 20"
            break;
        if(x==20):
            return 0;
            break;
    else:
        return names;


def show(names):
    for word in names:
        len_set=len(set(word))
        print word," ",len_set


for i in range(1):

    names=getText();
    if(names!=0):
        show(names);
    else:
        break;
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.