5

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.

GShocked
  • 3,606
  • 7
  • 25
  • 43
  • 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 – GShocked Jun 22 '15 at 04:03

5 Answers5

4

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,699
  • 17
  • 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. – GShocked 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. – GShocked 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. – GShocked 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
  • 32,647
  • 9
  • 86
  • 115
1
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,740
  • 11
  • 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
  • 2,956
  • 2
  • 21
  • 36
-2
def read(afilename):
    with open("afilename", "r") as file
       lines = file.readlines()
       lines.replace("[", "{")
       #place reset of code here in 
jamylak
  • 120,885
  • 29
  • 225
  • 225
AuzPython
  • 1
  • 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