2012-02-23 17 views
7

¡Buen día! Estoy usando Delphi XE y Indy TIdHTTP. Usando el método Get, obtengo un listado de directorio remoto y necesito analizarlo = obtener una lista de archivos con sus tamaños e indicaciones de tiempo, y distinguir los archivos y subdirectorios. Por favor, ¿hay una buena rutina para hacer eso? ¡Gracias de antemano! VojtechParse Lista de directorios HTTP

Aquí está la muestra:

<head> 
    <title>127.0.0.1 - /</title> 
</head> 
<body> 
    <H1>127.0.0.1 - /</H1><hr> 
<pre>  
    Mittwoch, 30. März 2011 12:01  &lt;dir&gt; <A HREF="/SubDir/">SubDir</A><br /> 
    Mittwoch, 9. Februar 2005 17:14   113 <A HREF="/file.txt">file.txt</A><br /> 
</pre> 
<hr> 
</body> 
+4

¿Tiene una muestra? En realidad, no existe una "lista de directorio" estándar (bueno, de hecho, hay * varios *, dependiendo del servidor y del sistema operativo en el que se esté ejecutando), y sin saber con qué está trabajando es difícil saber qué podría hacer. necesito hacer. –

+1

lo que necesita es un analizador HTML que crea un árbol, por lo que sería fácil encontrar todas las etiquetas "A" y actuar de acuerdo a sus necesidades. – ComputerSaysNo

+1

Si el servidor es compatible con WebDAV, una solución más robusta sería fácil de implementar con una biblioteca de cliente WebDAV. Cada actualización de versión de servidor o cambio de software rompería un analizador específico para este resultado HTML. – mjn

Respuesta

7

Teniendo en cuenta el ejemplo de código, supongo que la forma más rápida de analizar sería la siguiente:

  • Identificar el bloque <pre>...</pre> que contiene toda la lista de líneas Debería ser fácil.
  • Poner todo entre <pre> y </pre> en un TStringList. Cada línea es un archivo o carpeta, y el formato es muy simple.
  • Extraiga los enlaces de cada línea, extraiga la fecha, la hora y el tamaño si lo necesita. Mejor hecho con una expresión regular (tienes Delphi XE para que tengas Regex incorporado).
+6

+1. Es fácil cuando tienes una muestra. ¿No estás contento de haber preguntado? :) –

7

Esto debe darle un buen comienzo y la idea usando DOM:

uses 
    MSHTML, 
    ActiveX, 
    ComObj; 

procedure DocumentFromString(Document: IHTMLDocument2; const S: WideString); 
var 
    v: OleVariant; 
begin 
    v := VarArrayCreate([0, 0], varVariant); 
    v[0] := S; 
    Document.Write(PSafeArray(TVarData(v).VArray)); 
    Document.Close; 
end; 

function StripMultipleChar(const S: string; const C: Char): string; 
begin 
    Result := S; 
    while Pos(C + C, Result) <> 0 do 
    Result := StringReplace(Result, C + C, C, [rfReplaceAll]); 
end; 

procedure TForm1.Button1Click(Sender: TObject); 
var 
    Document: IHTMLDocument2; 
    Elements: IHTMLElementCollection; 
    Element: IHTMLElement; 
    I: Integer; 
    Line: string; 
begin 
    Document := CreateComObject(CLASS_HTMLDocument) as IHTMLDocument2; 
    DocumentFromString(Document, '<head>...'); // your HTML here 

    Elements := Document.all.tags('A') as IHTMLElementCollection; 
    for I := 0 to Elements.length - 1 do 
    begin 
    Element := Elements.item(I, '') as IHTMLElement; 
    Memo1.Lines.Add('A HREF=' + Element.getAttribute('HREF', 2)); 
    Memo1.Lines.Add('A innerText=' + Element.innerText); 

    // Text is returned immediately before the element 
    Line := (Element as IHTMLElement2).getAdjacentText('beforeBegin'); 

    // Line => "Mittwoch, 30. März 2011 12:01 <dir>" OR: 
    // Line => "Mittwoch, 9. Februar 2005 17:14 113"... 
    // I don't know what is the actual delimiter: 
    // It could be [space] or [tab] so we need to normalize the Line 
    // If it's tabs then it's easier because the timestamps also contains spaces 

    Line := Trim(Line); 
    Line := StripMultipleChar(Line, #32); // strip multiple Spaces sequences 
    Line := StripMultipleChar(Line, #9); // strip multiple Tabs sequences 

    // TODO: ParseLine (from right to left) 

    Memo1.Lines.Add(Line); 
    Memo1.Lines.Add('-------------'); 
    end; 
end; 

Salida:

A HREF=/SubDir/ 
A innerText=SubDir 
Mittwoch, 30. März 2011 12:01 <dir> 
------------- 
A HREF=/file.txt 
A innerText=file.txt 
Mittwoch, 9. Februar 2005 17:14 113 
------------- 

EDIT:
He cambiadoLa implementaciónes más simplificada. sin embargo, creo que la versión anterior era más optimizada para acelerar. considerando el hecho de que las líneas son muy cortas en longitud, no habrá muchas diferencias en el rendimiento.

+0

+1 porque funcionaría. El 'StripMultipleChar' podría simplificarse un poco. –

+0

se puede * simplificar * y * optimizar *. Tienes tantos bucles * while * que me da vueltas la cabeza: todo lo que necesitas es un bucle sencillo y directo. –

+0

@ Cosmin Prund, Ver mi edición.la función anterior se basaba realmente en una de las unidades JCL ... – kobik

Cuestiones relacionadas