Recortar caracteres

Iniciado por Eliza_loaeza, 20 Octubre 2015, 07:59 AM

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

Eliza_loaeza

Hola que tal, solicito de su ayuda con este problema estoy trabajando con vb y estoy cargando el contenido de un archivo .csv  ejemplo

"652394532592467968,"","","2015-10-09 08:05:52 +0000","Twitter Web Client","Hay ocasiones en la que mejor prevalecer ‪#‎Sisepuede‬ y seguir adelante.","","","",""
646843948586045440,"","","2015-09-24 00:29:49 +0000","<a href=""http://twitter.com"" rel=""nofollow"">Twitter Web Client</a>","#sisepuede Seguimos adelante :)","","","",""


en el archivo tengo aprox 1000 lineas, lo que quiero hacer es recortar todo y que solo quede el texto y pueda mostrarlo en un listbox

    Hay ocasiones en la que mejor prevalecer #Sisepuede y seguir adelante
Ojala puedan ayudarme saludos

Lekim

#1
Hola Eliza

Estaba intentado resolver tu problema hasta que me he dado cuenta de una cosa, y es que la cadena que muestra no tiene ningún sentido:

"652394532592467968,"","","2015-10-09 08:05:52 +0000","Twitter Web Client","Hay ocasiones en la que mejor prevalecer ‪#‎Sisepuede‬ y seguir adelante."


¿De verdad esto es así? Porque yo he buscado este tipo de archivo que nombras *.csv y no tienen ese formato.

Esto lo he sacado de WIN32API.CSV:
Element Name,Windows NT,Windows,Windows CE,Win32s,Component,Component Version,Header File,Import Library,Unicode,Element Type
ADsBuildEnumerator,4.0 or later,,,,ADSI,,adshlp.h,,,function
ADsBuildVarArrayInt,4.0 or later,,,,ADSI,,adshlp.h,,,function
ADsBuildVarArrayStr,4.0 or later,,,,ADSI,,adshlp.h,,,function
...



Creo que el archivo que intentas abrir se ha creado utilizando Open/For Append y Write. Este método crea los archivos con comillas:


NumFile = FreeFile
Open NombreFichero For Append As NumFile
Write #NumFile , Date$, Time$, Time$, "00:00:00"
Close NumFile


Se obtiene un archivo con el texto:

"10-20-2015","23:30:13","23:30:13","00:00:00"

Ahora al intentar leerlo la cosa se te complica. Para leerlo se hace de la siguiente manera:


NumFile = FreeFile
Open NombreFichero For Input As NumFile
Input #NumFile , Dato1, Dato2, Dato3, Dato4
Close NumFile


Ejemplo:
Código (vb) [Seleccionar]

Option Explicit

Private Sub cmdGuardar_Click()
Dim NombreFichero As String
Dim NumFile As Integer

NombreFichero = App.Path & "\Prueba.txt"
NumFile = FreeFile

Open NombreFichero For Append As NumFile
Write #NumFile , Date$, Time$, Time$, "00:00:00"
Close NumFile

'Se guarda con este formato
'"10-20-2015","23:27:56","23:27:56","00:00:00"
End Sub

Private Sub cmdAbrir_Click()
Dim NombreFichero As String
Dim Dato1 As String, Dato2 As String, Dato3  As String, Dato4 As String
Dim NumFile As Integer

NombreFichero = App.Path & "\Prueba.txt"
NumFile = FreeFile

Open NombreFichero For Input As NumFile
Input #NumFile , Dato1, Dato2, Dato3, Dato4
Close NumFile
Text1.Text = Dato1 & "  " & Dato2 & "  " & Dato3 & "  " & Dato4

'Se Abre con este formato (sin comillas)
'10-20-2015  23:27:56  23:27:56  00:00:00
End Sub



Voy a proponerte otra manera y luego si puedes me comentas si te sirve.

Saludos




Pues lo prometido es deuda.

Este código lee un archivo CSV  (normal, sin comillas) e introduce línea por línea en un ListBox

Código (vb) [Seleccionar]
Option Explicit
Private Sub Command1_Click()
 Dim Texto As String
 Dim DirFile As String

 '//Directorio donde se encuentra el archivo
 DirFile = App.Path & "\goURL_lr_photoshop_cz.csv"

 'Obtiene el texto
 Texto = LeerArchivo(DirFile)

 'Obtiene las líneas y las introduce en un ListBox
  Call CrearListaCompleta(Texto, List1)

End Sub
'//Proceso para obtener las líneas de un texto
Public Sub CrearListaCompleta(ByVal strLista As String, ByVal objList As ListBox)
   Dim Lineas() As String
   Dim i As Integer
   Lineas = Split(strLista, vbNewLine)
   For i = LBound(Lineas) To UBound(Lineas)
       If Lineas(i) <> "" Then objList.AddItem Lineas(i)
   Next
End Sub

Public Function LeerArchivo(ByVal DirFile As String) As String
 Dim FileName As String
 Dim File As Integer
 File = FreeFile
 FileName = DirFile
 Open FileName For Input As File
   LeerArchivo = Input(LOF(File), #File)
 Close File
End Function


Para guardar una archivo de texto (sin que se creen comillas) puedes usar esto:

Código (vb) [Seleccionar]
Public Function GuardarArchivoTexto(ByVal strTexto As String, ByVal FileName As String)
 Dim File As Integer, Cont As Integer, cDato As String
 On Error GoTo EvitarError
     File = FreeFile
 Open FileName For Binary As #File
For Cont = 1 To Len(strTexto)
   Put #File, Cont, strTexto
   Close #File
Next
EvitarError:
Select Case Err.Number
   Case 91
   Resume Next
End Select
End Function


Para llamarlo:
Código (vb) [Seleccionar]

Dim Texto as Sring
Texto = "¡Hola que tal!"
Call GuardarArchivoTexto(Texto , "C:\Prueba.txt")  


y si va a ser CSV

Código (vb) [Seleccionar]

Dim Texto as Sring
Texto = "¡Hola que tal!"
Call GuardarArchivoTexto(Texto , "C:\Prueba.csv")  



Espero que te sirva  ;)

Eliza_loaeza

#2
Hola Lekim Gracias por contestar
Asi es como cargo el archivo
Código (vbnet) [Seleccionar]
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
       Dim fileReader As System.IO.StreamReader
       Me.ListBox1.Items.Clear()
       Dim stringReader As String
       fileReader = My.Computer.FileSystem.OpenTextFileReader("C:\\tweets.csv")
       Do
           stringReader = fileReader.ReadLine()
           If Not stringReader Is Nothing Then

               If stringReader.Length <> 0 Then

                   Me.ListBox1.Items.Add(stringReader)

               End If
           End If
       Loop Until stringReader Is Nothing
       fileReader.Close()

  End Sub


lo envio a un listbox, lo que intento hacer es antes de cargar el archivo poder cortarlo. me ha servido de mucho tu informacion gracias saludos. ;-)


Mod: Los códigos deben ir en etiquetas GeSHi, esto es .NET, movido

Eleкtro

#3
Primero de nada, lee atentamente la nota que un compañero moderador te dejó en tu último comentario:
Cita de: Engel LexMod: Los códigos deben ir en etiquetas GeSHi, esto es .NET, movido

Debes seguir las normas del foro.





Cita de: Eliza_loaeza en 20 Octubre 2015, 07:59 AM"652394532592467968,"","","2015-10-09 08:05:52 +0000","Twitter Web Client","Hay ocasiones en la que mejor prevalecer ‪#‎Sisepuede‬ y seguir adelante.","","","",""
646843948586045440,"","","2015-09-24 00:29:49 +0000","<a href=""http://twitter.com"" rel=""nofollow"">Twitter Web Client</a>","#sisepuede Seguimos adelante :)","","","",""

El formato es inteligible si nos rejimos por un estándar, ya que todos los campos están cerrados por comillas dobles excepto el primer campo, donde en la primera linea o columna contiene una comilla doble (que no dos) así que el campo no está cerrado/delimitado, y en el de la segunda linea no contiene comillas. ¿Realmente eso lo tienes así o has cometido un fallo al publicar el ejemplo?.


¿Que significa para ti "recortarlo"?. Intenta ser más específico, ¿te refieres a partir el string en varios tokens/partes?.
Tampoco está claro si en el listbox estás intentando añadir las lineas completas o solamente los campos de alguna columna del CSV.
Da más detalles. . .



Si quieres partir el archivo en un array de lineas o strings entonces puedes utilizar la función System.IO.File.ReadAllLines (o en su defecto la extensión String.Split):
Código (vbnet) [Seleccionar]
Dim csvFilepath As String = "C:\file.csv"
Dim csvLines As String() = File.ReadAllLines(csvFilepath, Encoding.Default)

Me.ListBox1.Items.AddRange(csvLines)




Para otro tipo de tareas, como por ejemplo obtener todos los campos de una sola columna de la tabla CSV, puedes utilizar la class Microsoft.VisualBasic.FileIO.TextFieldParser:

Código (vbnet) [Seleccionar]
Dim csvFilepath As String = "C:\file.csv"
Dim csvFields As New List(Of String)

Using csvParser As New TextFieldParser(csvFilepath, Encoding.Default, detectEncoding:=True) With {
   .TextFieldType = FieldType.Delimited,
   .Delimiters = {","},
   .HasFieldsEnclosedInQuotes = True
}

   Do Until csvParser.EndOfData
       Try
           csvFields.Add(csvParser.ReadFields(0)) ' Campo 0.

       Catch ex As MalformedLineException
           ' Linea con formato incorrecto...

       End Try
   Loop

End Using

Me.ListBox1.Items.AddRange(csvFields.ToArray)


PD: No recomiendo recurrir a los miembros del namespace Microsoft.VisualBasic excepto para esta ocasión, ya que aparte de que no existe un equivalente en el resto de miembros de la librería de clases de .Net Framework, es tontería ponerse a reinventar la rueda desarrollando un parser de formato CSV. Siempre puedes utilizar librerías de terceros para .Net, como por ejemplo: https://github.com/JoshClose/CsvHelper o http://www.filehelpers.net/
De todas formas el desarollo de un parser específico para la tarea que requieres en cuestión, sería muy sencillo, pero no está del todo claro lo que pretendes.

Saludos








Eliza_loaeza

disculpa.
si es el archivo que descarga por defecto twitter, de estas lineas solo intento sacar los puros comentarios y eliminar el resto.

Eleкtro

#5
Cita de: Eliza_loaeza en 21 Octubre 2015, 07:36 AMde estas lineas solo intento sacar los puros comentarios y eliminar el resto.

Entonces puedes hacer esto, usando LINQ (por ejemplo):

Código (vbnet) [Seleccionar]
Imports System.Web

Dim csvFilepath As String = "C:\file.csv"

Dim comments As IEnumerable(Of String) =
   From line As String In File.ReadAllLines(csvFilepath, Encoding.UTF8)
   Select HttpUtility.HtmlDecode(line.Split(","c)(5).Trim(ControlChars.Quote))

Me.ListBox1.Items.AddRange(comments.ToArray)


Nota: Habría que comprobar como están escapados los caracteres ilegales, igual que el caracter de la coma.

Saludos








Lekim

#6
A partir de ahora en VB voy a preguntar si es para VB6 o para VB.NET  :-\

Siempre pasa igual :(

Los primero y antes de nada pon código, así sabremos que lenguaje usas o bien especifique que es para VB.NET.


Pero mantengo lo que dije pues he buscado ese tipo de archivos CSV, y hasta se pueden abrir con el notepad y son perfectamente legibles y sin comillas. No se quizás hay varios formatos.

Y también estoy de acuerdo con electro en que habría que ver como está escrito el texto, donde están las comas. Si no me equivoco debería ser algo similar a esto:

Element Name,Windows NT,Windows,Windows CE,Win32s,Component,Component Version,Header File,Import Library,Unicode,Element Type
ADsBuildEnumerator,4.0 or later,,,,ADSI,,adshlp.h,,,function
ADsBuildVarArrayInt,4.0 or later,,,,ADSI,,adshlp.h,,,function
ADsBuildVarArrayStr,4.0 or later,,,,ADSI,,adshlp.h,,,function


Job #, goURL, Reason, Destination
10101, learn_ps_processraw_cz, Automation/Batch Processing, http://av.adobe.com/russellbrown/ImageProcessorSM.mov
10101, learn_ps_viewglyphsai_cz, Type, http://av.adobe.com/russellbrown/OpenTypeSM.mov
10101, learn_ps_cs5_gsindex_cz, Getting Started and tutorials link on homepage, http://www.adobe.com
10101, ps_cs5_plugins_mac_cz, Download page for optional plug-ins, http://www.adobe.com
10101, ps_cs5_plugins_win_cz, Download page for optional plug-ins, http://www.adobe.com


Eleкtro

#7
Cita de: Lekim en 21 Octubre 2015, 09:21 AMPero mantengo lo que dije pues he buscado ese tipo de archivos CSV, y hasta se pueden abrir con el notepad y son perfectamente legibles y sin comillas. No se quizás hay varios formatos.

Te explico, un archivo CSV o Comma-separated values, es un archivo de texto plano el cual, como su propia definición indica, está delimitado por comas (u otro caracter). No le des más vueltas xD.

Imagínate la siguiente tabla pero representada en un archivo de texto, pues las comas o caracter delimitador se usarían para separar los campos y así poder identificar a que columna pertenecen.




Archivo.csv
; Columnas
firstname,lastname,username,password,email
; Campos
Jhon,Williams,Jhon williams,xFE3fghuw4D,mail@elhacker.net
etc...


Nota(s):
La primera linea a veces se utiliza para delimitar el nombre de las columnas, simplemente depende de la forma en la que quieras parsear el archivo, es decir, se asume que existen nombres de columnas o se asume lo contrario.
Las lineas que empiezan con ";" serían lineas de comentario, que podría ser cualquier otro caracter excepto el caracter delimitador.




Cita de: Lekim en 21 Octubre 2015, 09:21 AMestoy de acuerdo con electro en que habría que ver como está escrito el texto, donde están las comas. Si no me equivoco debería ser algo similar a esto

Creo que no entendiste bien lo que quise decir.

En el ejemplo del CSV de Twitter, los campos esán separados por comas, y cada campo está encerrado entre comillas dobles, pues bien, dentro de ese string encerrado cabe la posibilidad de que también contenga comas por el simple hecho de que en Twitter un usuario puede escribir comentarios utilizando comas, pero claro, ese caracter especial estará codificado/escapado para no crear conflictos con la delimitación de los campos.

El caso es que para que en la transformación del string/comentario no queden "residuous" de caracteres codificados habria que comprobar si Twitter usa codificación html normal o no para ese caracter de la coma, y yo no lo he comprobado por que ...en fin, por que no voy a ponerme a buscar comentarios que tengan comas en Twitter xD.

Saludos!








Lekim

#8
En cualquier caso el método par leerlo debe ser un equivalente al Input (debería haberlo), en VB6 pero desde VB.NET.

Si te fijas:
Element Name,Windows NT,Windows,Windows CE,Win32s,Component,Component Version,Header File,Import Library,Unicode,Element Type
ADsBuildEnumerator,4.0 or later,,,,ADSI,,adshlp.h,,,function


Aunque se vea desordenado sigue una lógica:
Dato1,Dato2,Dato3,Dato4,Dato5,...,Dato11

Donde ,,  es un espacio nulo es decir DatoX= ""

Y si su archivo lo muestra así:
"Dato1","Dato2","Dato3","Dato4","Dato5",...,"Dato11"

Viene a ser lo mismo.

Luego el sistema para leerlo debe ser similar al Input en VB.

Los archivos CSV que tengo yo, no son como los que pones de ejemplo. De hecho al abrirlo con el Excel se muestra todo en la misma columna tal cual como está en el archivo con comas y todo.

Por eso digo que debe haber varios formatos con misma extensión. Tengo clarísimo que los ejemplos que he puesto yo se han creado y se leen siguiendo un sistema similar al Input en VB6. Y por el ejemplo que ha puesto ella también deben ir por ahí los tiros.

Saludos



Utilizando el excel me he creado mi propio archivo
y se ha creado de la siguiente manera

1;124;9789
2;145;788
3;7878;65
4;9789;78
5;99;87
6;;88
7;788;7888
8;787;7
10;8;8


En el Excel son 9 filas y 3 columnas.
Luego está claro que, todo depende del sistema para crear este tipo de archivo. como dices
un archivo CSV o Comma-separated values, es un archivo de texto plano el cual, como su propia definición indica, está delimitado por comas (u otro caracter)

Yo creo que el de ella sigue un patrón IDÉNTICO al del Input en VB6 y no el Excel

Ya no lo doy más vueltas  :xD



Eleкtro

#9
Cita de: Lekim en 21 Octubre 2015, 10:20 AMPor eso digo que debe haber varios formatos con misma extensión.

Lekim, lo vuelvo a explicar de otra manera:

NO existen distintos tipos de formato CSV, un CSV es un archivo de TEXTO PLANO (archivo.txt) con la extensión modificada (archivo.csv) cuyo contenido está delimitado por comas u otro caracter que queda a elección de quien construye la tabla.

No hay más misterio, el formato es texto plano o plain text.

El único estándar del formato CSV es que los campos se delimiten mediante un caracter, en este caso la coma, y en el caso de tu Excel, el punto y coma. Luego hay factores adicionales como lineas de comentarios, columnas, delimitación de cadenas en los campos, etc..




Cita de: Lekim en 21 Octubre 2015, 10:20 AMLuego el sistema para leerlo debe ser similar al Input en VB.

Tengo clarísimo que los ejemplos que he puesto yo se han creado y se leen siguiendo un sistema similar al Input en VB6.

Pongamos claro que un CSV es un archivo de texto y NADA más, no ha sido especialmente diseñado o pensado para "leerse con VB", no tiene nada que ver una cosa con la otra, no lo mezclemos.

La función Input de VB6 simplemente lee el string de entrada hasta que el siguiente caracter CR, CR-LF o "," se encuentra y entonces podemos tokenizar/partir el string de esa forma. Es basicamente lo mismo que podemos hacer con la extensión String.Split en VB.Net, de la siguiente manera:

Código (vbnet) [Seleccionar]
Dim tokens As String() = <a>"hello",14,</a>.Value.Split({ControlChars.Cr, ControlChars.CrLf, ","c, ";"c}, StringSplitOptions.None)

For Each token As String In tokens
   Console.WriteLine(token.Trim({ControlChars.Quote}))
Next token


La función Input de VB6 se puede encontrar en el namespace Microsoft.VisualBasic de la librería de clases de .Net Framework, la cual ovbiamente está re-escrita usando puro código .Net, sin embargo, aún así la función está deprecada u obsoleta al tener un impacto grave en el rendimiento de la app. (POR COSAS ASÍ NO ME CANSARÉ DE REPETIR QUE NO SE DEBE RECURRIR A NINGÚN MIEMBRO DE ESTE NAMESPACE VB6-ESTILIZADO) y se recomienda en su defecto utilizar los miembros de My.Computer.FileSystem, que viene siendo exactamente lo mismo que publiqué en el ejemplo de mi primer post en este hilo.

Ejemplo:
Código (vbnet) [Seleccionar]
Using parser As TextFieldParser = My.Computer.FileSystem.OpenTextFieldParser("File.csv", {",", ";"})

   Do Until parser.EndOfData

       ' ...

   Loop

End Using


Hablando estrictamente ese sería su equivalente, la class Microsoft.VisualBasic.FileIO.TextFieldParser. Pero en mi opinión personal es mejor recurrir a un simple For para construir la logica del parser y así evitar por completo la utilización de ese namespace, así que para mi el equivalente sería String.Split aunque sería bastante más elaborado que el For que he publicado, pero no voy a reinventar la rueda.

Saludos!