System.OutOfMemoryException

Iniciado por Pisangas, 21 Diciembre 2017, 20:04 PM

0 Miembros y 1 Visitante están viendo este tema.

Pisangas

Buenas tardes,

Me colaboraron con un PowerShell que lee un archivo CSV y transfiere a otro archivo CSV las columnas que yo elija, hasta aquí todo bien, funciona con archivos pequeños y de pocos registros, sin embargo estoy intentando cargar un archivo que pesa cerca de 1.5 Gb y según

Get-Content miarchivo.csv | Measure-Object

Count    : 2563236


La cuestion es que según yo al cargar el archivo se queda sin memoria, se recibe el error: "Import-Csv : Exception of type 'System.OutOfMemoryException' was thrown"

algo para superar este inconveniente?

Eleкtro

#1
Cita de: Pisangas en 21 Diciembre 2017, 20:04 PMalgo para superar este inconveniente?

Prueba con las clases de .NET Framework (esto tecnicamente ya no sería puto código PowerShell):

script.ps1
$lines = [System.IO.File]::ReadLines( "C:\File.csv", [System.Text.Encoding]::Default )
[System.Int32] $count = ($lines).Count

Write-Host $count


No estoy muy seguro de si funcionará. Por un lado la clase IEnumerable (la cual es parecida a un Array en la programación) es un tipo de evaluación vaga (Lazy Evaluarion Type), esto quiere decir que las lineas del contenido del archivo.csv (o dicho de otra forma, los elementos del Array) solo se cargarán en memoria a medida que vaya siendo realmente necesario y se deasignará de la memoria cuando ya no sea necesario, por lo que en principio no sufririas un desbordamiento de memoria, sin embargo al usar la propiedad IEnumerable.Count tiene que iterar todos los elementos de la colección IEnumerable para hacer el conteo... así que no estoy seguro de lo que sucederá, pruébalo y me dices.

Saludos.








Pisangas

#2
Method invocation failed because [System.IO.File] doesn't contain a method named 'ReadLines'.

At line:2 char:37

Lo estoy haciendo sobre el PowerShell, es correcto?

Eleкtro

#3
Cita de: Pisangas en 21 Diciembre 2017, 22:09 PM
Lo estoy haciendo sobre el PowerShell, es correcto?

si.




Cita de: Pisangas en 21 Diciembre 2017, 22:09 PM
por el momento me dice Method invocation failed because [System.IO.File] doesn't contain a method named 'ReadLines'.

Sin embargo validando la clase ReadLines si pertenece al objeto System.IO.File

La función System.IO.File.ReadLines() fue introducida en la versión 4.0 de .NET Framework, así que necesitas tener instalada esa versión (como mínimo) o una superior en tu Windows. Si eso no es posible, entonces mo podrás usar ese código. Puedes probar con la función "ReadAllLines" en vez de "ReadLines" (solo tienes que cambiarle el nombre a esa parte del código), pero el resultado me temo que será muy distinto ( ya que esa función devuelve un Array como tal, así que probablemente se te desbordará la memoria, pero bueno, por probar... puedes intentarlo a ver. )

Saludos








Pisangas

Actualizo el .NET y te aviso cualquier cosa, gracias!

Pisangas

tengo la versión 4.7

Cita de: Eleкtro en 21 Diciembre 2017, 22:31 PM
si.




La función System.IO.File.ReadLines() fue introducida en la versión 4.0 de .NET Framework, así que necesitas tener instalada esa versión (como mínimo) o una superior en tu Windows. Si eso no es posible, entonces mo podrás usar ese código. Puedes probar con la función "ReadAllLines" en vez de "ReadLines" (solo tienes que cambiarle el nombre a esa parte del código), pero el resultado me temo que será muy distinto ( ya que esa función devuelve un Array como tal, así que probablemente se te desbordará la memoria, pero bueno, por probar... puedes intentarlo a ver. )

Saludos

Pisangas

Me temo que ocurre igual


Exception calling "ReadAllLines" with "1" argument(s): "Exception of type 'System.OutOfMemoryException' was thrown."

Eleкtro

Cita de: Pisangas en 21 Diciembre 2017, 23:03 PM
Me temo que ocurre igual


Exception calling "ReadAllLines" with "1" argument(s): "Exception of type 'System.OutOfMemoryException' was thrown."

Eso te dije, que probablemente te ocurriría igual con "ReadAllLines". Prueba con "ReadLines", si tienes .NET Framework 4.7 deberías poder usar esa función, si te sale algún error, muestra el mensaje de error.

saludos








Pisangas

#8
No se, responde igual


Method invocation failed because [System.IO.File] doesn't contain a method named 'ReadLines'.
At line:1 char:37
+ $lines = [System.IO.File]::ReadLines <<<< ( "C:\xxxx.csv", [System.Text.Encoding]::Default )
   + CategoryInfo          : InvalidOperation: (ReadLines:String) [], RuntimeException
   + FullyQualifiedErrorId : MethodNotFound



y cuando lo cambio por la clase ReadAllLines arroja excepcion de memoria al cargar el csv

Exception calling "ReadAllLines" with "2" argument(s): "Exception of type 'System.OutOfMemoryException' was thrown."
At line:1 char:40

existe alguna manera de configurar en algún lugar un valor de memoria mas alto?

[MOD] usar "modificar" para añadir comentarios, no hacer doble post.

Pisangas

#9
Bueno creo que de tanto buscar e intentar encontré la solución.

Como lo entendi, no era necesario esperar la importacion, luego la seleccion de las columnas para al final exportar, entonces por que no hacerlo todo al mismo tiempo


$csv = Import-Csv -Path "C:\xxx\xxx.csv" -Delimiter "|" | select "DATO1","DATO2","DATOn" | export-CSV C:\xxx\xxx.csv

tal vez sea una "chambonada"pero me funciono. Mil gracias por todo el apoyo.