7

I have a ~600MB Roblox type .mesh file, which reads like a text file in any text editor. I have the following code below:

mesh = open("file.mesh", "r").read()
mesh = mesh.replace("[", "{").replace("]", "}").replace("}{", "},{")
mesh = "{"+mesh+"}"
f = open("p2t.txt", "w")
f.write(mesh)

It returns:

Traceback (most recent call last):
  File "C:\TheDirectoryToMyFile\p2t2.py", line 2, in <module>
    mesh = mesh.replace("[", "{").replace("]", "}").replace("}{", "},{")
MemoryError

Here is a sample of my file:

[-0.00599, 0.001466, 0.006][0.16903, 0.84515, 0.50709][0.00000, 0.00000, 0][-0.00598, 0.001472, 0.00599][0.09943, 0.79220, 0.60211][0.00000, 0.00000, 0]

What can I do?

Edit:

I'm not sure what the head, follow, and tail commands are in that other thread that marked this as a duplicate. I tried to use it, but couldn't get it to work. The file is also one giant line, it isn't split into lines.

Rontron
  • 3,963
  • 7
  • 26
  • 44
  • try doing the replace's one at a time. Try reading some Tutorials. – wwii Jun 22 '15 at 03:49
  • possible duplicate of [Read large text files in Python, line by line without loading it in to memory](http://stackoverflow.com/questions/6475328/read-large-text-files-in-python-line-by-line-without-loading-it-in-to-memory) – Pruthvi Raj Jun 22 '15 at 03:55
  • It may not be a duplicate if the file has no lines. @GShocked Is the file split into lines? – jamylak Jun 22 '15 at 03:57
  • Case you change order to replace to mesh.replace('][','},{').replace("[", "{").replace("]", "}") it will be done faster – mmachine Jun 22 '15 at 04:02
  • @jamylak No, it is all in one line – Rontron Jun 22 '15 at 04:03
  • If the file is all one line, I am **extremely** doubtful that it "reads like a text file in any text editor". Most text editors I've seen will process files extremely slowly when they have very long lines, and use many times as much memory as the size of the file. – Karl Knechtel Aug 28 '22 at 20:34

5 Answers5

5

You need to read one bite per iteration, analyze it and then write to another file or to sys.stdout. Try this code:

mesh = open("file.mesh", "r")
mesh_out = open("file-1.mesh", "w")

c = mesh.read(1)

if c:
    mesh_out.write("{")
else:
    exit(0)
while True:
    c = mesh.read(1)
    if c == "":
        break

    if c == "[":
        mesh_out.write(",{")
    elif c == "]":
        mesh_out.write("}")
    else:
        mesh_out.write©

UPD:

It works really slow (thanks to jamylak). So I've changed it:

import sys
import re


def process_char(c, stream, is_first=False):
    if c == '':
        return False
    if c == '[':
        stream.write('{' if is_first else ',{')
        return True
    if c == ']':
        stream.write('}')
        return True


def process_file(fname):
    with open(fname, "r") as mesh:
        c = mesh.read(1)
        if c == '':
            return
        sys.stdout.write('{')

        while True:
            c = mesh.read(8192)
            if c == '':
                return

            c = re.sub(r'\[', ',{', c)
            c = re.sub(r'\]', '}', c)
            sys.stdout.write(c)


if __name__ == '__main__':
    process_file(sys.argv[1])

So now it's working ~15 sec on 1.4G file. To run it:

$ python mesh.py file.mesh > file-1.mesh
Pavel Reznikov
  • 2,968
  • 1
  • 18
  • 17
  • nice. see also this question http://stackoverflow.com/questions/2872381/how-to-read-a-file-byte-by-byte-in-python-and-how-to-print-a-bytelist-as-a-binar – maxymoo Jun 22 '15 at 03:59
  • Might be a good idea to work *within* a context manager using a ```with``` statement. ```mesh_out``` should be opened for *appending* – wwii Jun 22 '15 at 04:01
  • 1
    Reading `1` byte at a time is super slow though. You should use a buffer size of eg. default `8192` and run `.replace()` on each chunk – jamylak Jun 22 '15 at 04:02
  • I'm wondering how you handle the case of `},{` however. Its not too hard will just make things more complicated similar to how this answer deals with newlines: http://stackoverflow.com/questions/2301789/read-a-file-in-reverse-order-using-python – jamylak Jun 22 '15 at 04:03
  • I will try this now, it hasn't completed yet though. The second `elif` is missing a `:`, but I fixed that. – Rontron Jun 22 '15 at 04:08
  • @GShocked I would recommend you change `.read(1)` to `.read(8192)` or adjusted. And change the `if` statements to 2 `.replace`s and it will complete faster. (and then also fix anything else in code if necessary) – jamylak Jun 22 '15 at 04:12
  • @jamylak I'll try that, but it is more than half done so I will wait a bit to do that. – Rontron Jun 22 '15 at 04:13
  • I need to change the file because I just realized that the output is too large for Roblox. I will make the mesh smaller. This script partly worked. It didn't surround the entire thing with another pair of curly braces though. – Rontron Jun 22 '15 at 04:25
2

You could do it line by line:

mesh = open("file.mesh", "r")
with open("p2t.txt", "w") as f:
   for line in mesh:
      line= line.replace("[", "{").replace("]", "}").replace("}{", "},{")
      line = "{"+line +"}"
      f.write(line)
maxymoo
  • 35,286
  • 11
  • 92
  • 119
2
BLOCK_SIZE = 1 << 15
with open(input_file, 'rb') as fin, open(output_file, 'wb') as fout:
    for block in iter(lambda: fin.read(BLOCK_SIZE), b''):
        # do your replace
        fout.write(block)
LittleQ
  • 1,860
  • 1
  • 12
  • 14
0
import os
f = open('p2f.txt','w')
with open("file.mesh") as mesh:
  while True:
    c = mesh.read(1)
    if not c:
      f.seek(-1,os.SEEK_END)
      f.truncate()
      break
    elif c == '[':
        f.write('{')
    elif c == ']':
        f.write('},')
   else:
       f.write(c)

p2f.txt:

{-0.00599, 0.001466, 0.006},{0.16903, 0.84515, 0.50709},{0.00000, 0.00000, 0},{-0.00598, 0.001472, 0.00599},{0.09943, 0.79220, 0.60211},{0.00000, 0.00000, 0}
Pruthvi Raj
  • 3,016
  • 2
  • 22
  • 36
0
def read(afilename):
    with open("afilename", "r") as file
       lines = file.readlines()
       lines.replace("[", "{")
       #place reset of code here in 
jamylak
  • 128,818
  • 30
  • 231
  • 230
AuzPython
  • 21
  • 2
  • that would depend on the size of the file being read/written ??. on a small file, could you say you would notice it ? – AuzPython Jun 22 '15 at 05:38
  • 1
    On a small file you would not notice. but the question is specifically about "opening large files" and says "600mb file". Also its bad practice to use `.readlines()`, i never use it – jamylak Jun 22 '15 at 08:51