5 Stimmen

Wie kann ich Python verwenden, um eine txt-Datei mit fester Breite in eine csv-Datei zu konvertieren?

Ich habe im Internet gesucht, konnte aber keine Antwort auf meine Frage finden. Ich muss eine txt-Datei in eine csv-Datei konvertieren. Ich habe herausgefunden, wie man das mit Begrenzungszeichen macht, aber die txt-Datei hat keine Begrenzungszeichen oder Kopfzeilen, also muss ich Zahlen mit fester Breite setzen. Die Datei hat Millionen von Datensätzen. Die Breiten der Spalten sind 10, 60, 60, 60, 30, 2, 3, 6, 9, 5, 6, 12, 12, 5, 3, 12, 12, 5, 3.

Meine zwei Herausforderungen sind: 1. Konvertierung der Datei in csv mit den oben genannten festen Breiten. 2. Kopfzeilen einfügen.

Die Daten sehen in etwa so aus:

0000000626ISOCKE BBBB ZZZZZ TW DARTMOUTH 10 FDSAF DR DARTMOUTH CASN 7H44DR SAAB -11.111111 22.2222222 000 -33.333333 44.4444444 000
0000000627ISOCKE FFFF TTTTT TW HALIFAX 3367 FDSAF RD HALIFAX CASN 8C5ASE SAAB -55.555555 66.6666666 000 -77.777777 88.8888888 000
0000000628ISOCKE RE CHARLOTTETOWN 449 UYRNT ECSARW RD CHARLOTTETOWN CAPE CSE8HR SAAB -99.999999 11.1111111 000 -22.222222 33.3333333 000

Auch hier konnte ich die Datei nur in eine CSV-Datei konvertieren, aber nicht in das richtige Format mit diesem Code:

import csv
rf = open(r'C:\Users\...New Folder\practice.txt', 'r') #input file handle
wf = open(r'C:\Users\...New Folder\Book1.csv','w') #output file handle
writer = csv.writer(wf)

for row in rf.readlines():
    writer.writerow(row.split())
rf.close() # close input file handle
wf.close() # close output file handle

5voto

Verwenden Sie struct um jede Reihe mit fester Breite auseinanderzureißen und gegebenenfalls zu beschneiden.

4voto

John Machin Punkte 78125

Verwenden Sie Slice-Objekte:

>>> widths = 1,2,3
>>> slices = []
>>> offset = 0
>>> for w in widths:
...     slices.append(slice(offset, offset + w))
...     offset += w
...
>>> slices
[slice(0, 1, None), slice(1, 3, None), slice(3, 6, None)]
>>> pieces = ["abcdef"[slice] for slice in slices]
>>> pieces
['a', 'bc', 'def']
>>>

4voto

just10minutes Punkte 541

Falls jemand noch nach einer Lösung sucht, habe ich ein kleines Skript in Python entwickelt. Es ist einfach zu benutzen, vorausgesetzt man hat Python 3.5

https://github.com/just10minutes/FixedWidthToDelimited/blob/master/FixedWidthToDelimiter.py

"""
This script will convert Fixed width File into Delimiter File, tried on Python 3.5 only
Sample run: (Order of argument doesnt matter)
python ConvertFixedToDelimiter.py -i SrcFile.txt -o TrgFile.txt -c Config.txt -d "|"
Inputs are as follows
1. Input FIle - Mandatory(Argument -i) - File which has fixed Width data in it
2. Config File - Optional (Argument -c, if not provided will look for Config.txt file on same path, if not present script will not run)
    Should have format as
    FieldName,fieldLength
    eg:
    FirstName,10
    SecondName,8
    Address,30
    etc:
3. Output File - Optional (Argument -o, if not provided will be used as InputFIleName plus Delimited.txt)
4. Delimiter - Optional (Argument -d, if not provided default value is "|" (pipe))
"""
from collections import OrderedDict
import argparse
from argparse import ArgumentParser
import os.path
import sys

def slices(s, args):
    position = 0
    for length in args:
        length = int(length)
        yield s[position:position + length]
        position += length

def extant_file(x):
    """
    'Type' for argparse - checks that file exists but does not open.
    """
    if not os.path.exists(x):
        # Argparse uses the ArgumentTypeError to give a rejection message like:
        # error: argument input: x does not exist
        raise argparse.ArgumentTypeError("{0} does not exist".format(x))
    return x

parser = ArgumentParser(description="Please provide your Inputs as -i InputFile -o OutPutFile -c ConfigFile")
parser.add_argument("-i", dest="InputFile", required=True,    help="Provide your Input file name here, if file is on different path than where this script resides then provide full path of the file", metavar="FILE", type=extant_file)
parser.add_argument("-o", dest="OutputFile", required=False,    help="Provide your Output file name here, if file is on different path than where this script resides then provide full path of the file", metavar="FILE")
parser.add_argument("-c", dest="ConfigFile", required=False,   help="Provide your Config file name here,File should have value as fieldName,fieldLength. if file is on different path than where this script resides then provide full path of the file", metavar="FILE",type=extant_file)
parser.add_argument("-d", dest="Delimiter", required=False,   help="Provide the delimiter string you want",metavar="STRING", default="|")

args = parser.parse_args()

#Input file madatory
InputFile = args.InputFile
#Delimiter by default "|"
DELIMITER = args.Delimiter

#Output file checks
if args.OutputFile is None:
    OutputFile = str(InputFile) + "Delimited.txt"
    print ("Setting Ouput file as "+ OutputFile)
else:
    OutputFile = args.OutputFile

#Config file check
if args.ConfigFile is None:
    if not os.path.exists("Config.txt"):
        print ("There is no Config File provided exiting the script")
        sys.exit()
    else:
        ConfigFile = "Config.txt"
        print ("Taking Config.txt file on this path as Default Config File")
else:
    ConfigFile = args.ConfigFile

fieldNames = []
fieldLength = []
myvars = OrderedDict()

with open(ConfigFile) as myfile:
    for line in myfile:
        name, var = line.partition(",")[::2]
        myvars[name.strip()] = int(var)
for key,value in myvars.items():
    fieldNames.append(key)
    fieldLength.append(value)

with open(OutputFile, 'w') as f1:
    fieldNames = DELIMITER.join(map(str, fieldNames))
    f1.write(fieldNames + "\n")
    with open(InputFile, 'r') as f:
        for line in f:
            rec = (list(slices(line, fieldLength)))
            myLine = DELIMITER.join(map(str, rec))
            f1.write(myLine + "\n")

0voto

Gnudiff Punkte 4101

Für mich persönlich hat das FixedWidth-Modul sehr gut funktioniert.

Siehe https://pypi.org/project/FixedWidth/

Es ist ein wenig Einstellungsarbeit erforderlich, aber Sie können Ihre Felder dann als String, numerisch (mit der Möglichkeit, die Genauigkeit anzugeben), linksbündig oder rechtsbündig beschreiben, was ist

q

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X